mirror of
https://github.com/LiBwrt-op/openwrt-6.x.git
synced 2025-12-16 16:57:28 +00:00
Update QCA Source
This commit is contained in:
parent
07089cedb8
commit
acb476b50e
93
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
93
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@ -1,93 +0,0 @@
|
||||
name: Bug report
|
||||
description: Create a bug report to help us improve
|
||||
labels:
|
||||
- bug
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: A clear and concise description of the bug.
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: ImmortalWrt version
|
||||
description: |
|
||||
The ImmortalWrt release or commit hash where this bug occurs (use command below).
|
||||
```. /etc/openwrt_release && echo $DISTRIB_REVISION```
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: release
|
||||
attributes:
|
||||
label: ImmortalWrt release
|
||||
description: |
|
||||
The ImmortalWrt release or commit hash where this bug occurs (use command below).
|
||||
```. /etc/openwrt_release && echo $DISTRIB_RELEASE```
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: target
|
||||
attributes:
|
||||
label: ImmortalWrt target/subtarget
|
||||
description: |
|
||||
The ImmortalWrt target and subtarget where this bug is observed (use command below).
|
||||
```. /etc/openwrt_release && echo $DISTRIB_TARGET```
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: device
|
||||
attributes:
|
||||
label: Device
|
||||
description: |
|
||||
The device exhibiting this bug (if unsure, use command below).
|
||||
```cat /tmp/sysinfo/model```
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: image_kind
|
||||
attributes:
|
||||
label: Image kind
|
||||
options:
|
||||
- Official downloaded image
|
||||
- Self-built image
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduce
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Steps to reproduce the reported behaviour.
|
||||
- type: textarea
|
||||
id: behaviour
|
||||
attributes:
|
||||
label: Actual behaviour
|
||||
description: A clear and concise description of what actually happens.
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected behaviour
|
||||
description: A clear and concise description of what you expected to happen.
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional info
|
||||
description: Add any additional info you think might be helfpul.
|
||||
- type: textarea
|
||||
id: diffconfig
|
||||
attributes:
|
||||
label: Diffconfig
|
||||
description: |
|
||||
In case of a self-built image, please attach diffconfig.
|
||||
```./scripts/diffconfig.sh```
|
||||
render: text
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Terms
|
||||
description: By submitting this issue, you agree to the terms below.
|
||||
options:
|
||||
- label: I am reporting an issue for ImmortalWrt, not an unsupported fork.
|
||||
required: true
|
||||
9
.github/ISSUE_TEMPLATE/config.yml
vendored
9
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,9 +0,0 @@
|
||||
---
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: ImmortalWrt community
|
||||
url: https://t.me/ctcgfw_openwrt_discuss
|
||||
about: Consider reaching out to our community to get help. ImmortalWrt is a complex software project with many pitfalls; there is a good chance someone can help you solve your issue in no time.
|
||||
- name: OpenWrt documentation
|
||||
url: https://openwrt.org/docs/start
|
||||
about: The OpenWrt documentation contains a lot of valuable information.
|
||||
64
.github/workflows/Update-Athena-LED.yml
vendored
Normal file
64
.github/workflows/Update-Athena-LED.yml
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
name: Update-Athena-LED
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: 0 0 * * 0
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
|
||||
permissions: write-all
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Delete old Releases and Workflows
|
||||
uses: ophub/delete-releases-workflows@main
|
||||
with:
|
||||
gh_token: ${{secrets.GITHUB_TOKEN}}
|
||||
delete_workflows: true
|
||||
workflows_keep_day: 0
|
||||
|
||||
update:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: cleanup
|
||||
steps:
|
||||
- name: Checkout Projects
|
||||
uses: actions/checkout@main
|
||||
|
||||
- name: Update Athena LED
|
||||
run: |
|
||||
cd ./package/emortal/
|
||||
PKG_NAME=luci-app-athena-led
|
||||
|
||||
LOCAL_HASH=$(cat "./$PKG_NAME/.latest_commit" 2>/dev/null || echo "none")
|
||||
REMOTE_HASH=$(curl -sL https://api.github.com/repos/NONGFAH/luci-app-athena-led/commits/main | jq -r '.sha' | cut -c1-8)
|
||||
|
||||
if [[ "$LOCAL_HASH" != "$REMOTE_HASH" ]]; then
|
||||
rm -rf ./$PKG_NAME
|
||||
curl -sL -o ./athena-led.zip https://github.com/NONGFAH/luci-app-athena-led/archive/refs/heads/main.zip
|
||||
unzip ./athena-led.zip -d ./
|
||||
mv ./luci-app-athena-led-main ./$PKG_NAME && rm -rf ./athena-led.zip
|
||||
chmod +x -R ./$PKG_NAME/root/usr/sbin/* && chmod +x -R ./$PKG_NAME/root/etc/init.d/*
|
||||
|
||||
echo "$PKG_NAME has been updated to $REMOTE_HASH!"
|
||||
|
||||
echo "$REMOTE_HASH" > "./$PKG_NAME/.latest_commit"
|
||||
echo "PKG_NAME=$PKG_NAME" >> "$GITHUB_ENV"
|
||||
echo "REMOTE_HASH=$REMOTE_HASH" >> "$GITHUB_ENV"
|
||||
else
|
||||
echo "$PKG_NAME is already the latest!"
|
||||
fi
|
||||
|
||||
[ -z "$(git status -s)" ] || echo -e "CHANGE_STAT=1" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Commit Changes
|
||||
if: ${{ env.CHANGE_STAT }}
|
||||
run: |
|
||||
git config --local user.name "github-actions[bot]"
|
||||
git config --local user.email "<github-actions[bot]@users.noreply.github.com>"
|
||||
git add .
|
||||
git commit -m "${{env.PKG_NAME}}: update version to ${{env.REMOTE_HASH}}"
|
||||
git push -f origin HEAD:main
|
||||
@ -38,3 +38,5 @@ source "target/sdk/Config.in"
|
||||
source "target/toolchain/Config.in"
|
||||
|
||||
source "tmp/.config-package.in"
|
||||
|
||||
source "config/Config-ipq.in"
|
||||
|
||||
96
README.md
96
README.md
@ -1,93 +1,15 @@
|
||||
<img src="https://avatars.githubusercontent.com/u/53193414?s=200&v=4" alt="logo" width="200" height="200" align="right">
|
||||
# 分支说明
|
||||
main 为高通专用,无法编译其他平台,带满血NSS驱动。
|
||||
|
||||
# Project ImmortalWrt
|
||||
owrt 为多平台通用,可编译高通平台,但没有NSS驱动。
|
||||
|
||||
ImmortalWrt is a fork of [OpenWrt](https://openwrt.org), with more packages ported, more devices supported, default optimized profiles and localization modifications for mainland China users.<br/>
|
||||
Compared to upstream, we allow to use (non-upstreamable) modifications/hacks to provide better feature/performance/support.
|
||||
# 自用 ImmortalWRT
|
||||
高通部分源码取自以下项目:
|
||||
|
||||
Default login address: http://192.168.1.1 or http://immortalwrt.lan, username: __root__, password: _none_.
|
||||
https://github.com/JiaY-shi/openwrt.git
|
||||
|
||||
## Download
|
||||
Built firmware images are available for many architectures and come with a package selection to be used as WiFi home router. To quickly find a factory image usable to migrate from a vendor stock firmware to ImmortalWrt, try the *Firmware Selector*.
|
||||
https://github.com/LiBwrt/openwrt-6.x.git
|
||||
|
||||
- [ImmortalWrt Firmware Selector](https://firmware-selector.immortalwrt.org/)
|
||||
https://github.com/qosmio/openwrt-ipq.git
|
||||
|
||||
If your device is supported, please follow the **Info** link to see install instructions or consult the support resources listed below.
|
||||
|
||||
## Development
|
||||
To build your own firmware you need a GNU/Linux, BSD or macOS system (case sensitive filesystem required). Cygwin is unsupported because of the lack of a case sensitive file system.<br/>
|
||||
|
||||
### Requirements
|
||||
To build with this project, Debian 11 is preferred. And you need use the CPU based on AMD64 architecture, with at least 4GB RAM and 25 GB available disk space. Make sure the __Internet__ is accessible.
|
||||
|
||||
The following tools are needed to compile ImmortalWrt, the package names vary between distributions.
|
||||
|
||||
- Here is an example for Debian/Ubuntu users:<br/>
|
||||
- Method 1:
|
||||
<details>
|
||||
<summary>Setup dependencies via APT</summary>
|
||||
|
||||
```bash
|
||||
sudo apt update -y
|
||||
sudo apt full-upgrade -y
|
||||
sudo apt install -y ack antlr3 asciidoc autoconf automake autopoint binutils bison build-essential \
|
||||
bzip2 ccache clang cmake cpio curl device-tree-compiler ecj fastjar flex gawk gettext gcc-multilib \
|
||||
g++-multilib git gnutls-dev gperf haveged help2man intltool lib32gcc-s1 libc6-dev-i386 libelf-dev \
|
||||
libglib2.0-dev libgmp3-dev libltdl-dev libmpc-dev libmpfr-dev libncurses-dev libpython3-dev \
|
||||
libreadline-dev libssl-dev libtool libyaml-dev libz-dev lld llvm lrzsz mkisofs msmtp nano \
|
||||
ninja-build p7zip p7zip-full patch pkgconf python3 python3-pip python3-ply python3-docutils \
|
||||
python3-pyelftools qemu-utils re2c rsync scons squashfs-tools subversion swig texinfo uglifyjs \
|
||||
upx-ucl unzip vim wget xmlto xxd zlib1g-dev zstd
|
||||
```
|
||||
</details>
|
||||
- Method 2:
|
||||
```bash
|
||||
sudo bash -c 'bash <(curl -s https://build-scripts.immortalwrt.org/init_build_environment.sh)'
|
||||
```
|
||||
|
||||
Note:
|
||||
- Do everything as an unprivileged user, not root, without sudo.
|
||||
- Using CPUs based on other architectures should be fine to compile ImmortalWrt, but more hacks are needed - No warranty at all.
|
||||
- You must __not__ have spaces or non-ascii characters in PATH or in the work folders on the drive.
|
||||
- If you're using Windows Subsystem for Linux (or WSL), removing Windows folders from PATH is required, please see [Build system setup WSL](https://openwrt.org/docs/guide-developer/build-system/wsl) documentation.
|
||||
- Using macOS as the host build OS is __not__ recommended. No warranty at all. You can get tips from [Build system setup macOS](https://openwrt.org/docs/guide-developer/build-system/buildroot.exigence.macosx) documentation.
|
||||
- For more details, please see [Build system setup](https://openwrt.org/docs/guide-developer/build-system/install-buildsystem) documentation.
|
||||
|
||||
### Quickstart
|
||||
1. Run `git clone -b <branch> --single-branch --filter=blob:none https://github.com/immortalwrt/immortalwrt` to clone the source code.
|
||||
2. Run `cd immortalwrt` to enter source directory.
|
||||
3. Run `./scripts/feeds update -a` to obtain all the latest package definitions defined in feeds.conf / feeds.conf.default
|
||||
4. Run `./scripts/feeds install -a` to install symlinks for all obtained packages into package/feeds/
|
||||
5. Run `make menuconfig` to select your preferred configuration for the toolchain, target system & firmware packages.
|
||||
6. Run `make` to build your firmware. This will download all sources, build the cross-compile toolchain and then cross-compile the GNU/Linux kernel & all chosen applications for your target system.
|
||||
|
||||
### Related Repositories
|
||||
The main repository uses multiple sub-repositories to manage packages of different categories. All packages are installed via the OpenWrt package manager called opkg. If you're looking to develop the web interface or port packages to ImmortalWrt, please find the fitting repository below.
|
||||
- [LuCI Web Interface](https://github.com/immortalwrt/luci): Modern and modular interface to control the device via a web browser.
|
||||
- [ImmortalWrt Packages](https://github.com/immortalwrt/packages): Community repository of ported packages.
|
||||
- [OpenWrt Routing](https://github.com/openwrt/routing): Packages specifically focused on (mesh) routing.
|
||||
- [OpenWrt Video](https://github.com/openwrt/video): Packages specifically focused on display servers and clients (Xorg and Wayland).
|
||||
|
||||
## Support Information
|
||||
For a list of supported devices see the [OpenWrt Hardware Database](https://openwrt.org/supported_devices)
|
||||
### Documentation
|
||||
- [Quick Start Guide](https://openwrt.org/docs/guide-quick-start/start)
|
||||
- [User Guide](https://openwrt.org/docs/guide-user/start)
|
||||
- [Developer Documentation](https://openwrt.org/docs/guide-developer/start)
|
||||
- [Technical Reference](https://openwrt.org/docs/techref/start)
|
||||
|
||||
### Support Community
|
||||
- Support Chat: group [@ctcgfw_openwrt_discuss](https://t.me/ctcgfw_openwrt_discuss) on [Telegram](https://telegram.org/).
|
||||
- Support Chat: group [#immortalwrt](https://matrix.to/#/#immortalwrt:matrix.org) on [Matrix](https://matrix.org/).
|
||||
|
||||
## License
|
||||
ImmortalWrt is licensed under [GPL-2.0-only](https://spdx.org/licenses/GPL-2.0-only.html).
|
||||
|
||||
## Acknowledgements
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="https://dlercloud.com/"><img src="https://user-images.githubusercontent.com/22235437/111103249-f9ec6e00-8588-11eb-9bfc-67cc55574555.png" width="183" height="52" border="0" alt="Dler Cloud"></a></td>
|
||||
<td><a href="https://www.jetbrains.com/"><img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jb_square.png" width="120" height="120" border="0" alt="JetBrains Black Box Logo logo"></a></td>
|
||||
<td><a href="https://sourceforge.net/"><img src="https://sourceforge.net/sflogo.php?type=17&group_id=3663829" alt="SourceForge" width=200></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
https://github.com/King-Of-Knights/openwrt-6.x.git
|
||||
|
||||
145
config/Config-ipq.in
Normal file
145
config/Config-ipq.in
Normal file
@ -0,0 +1,145 @@
|
||||
# vim: set ft=kconfig
|
||||
menu "Qualcomm IPQ Options"
|
||||
|
||||
comment "Kernel build options"
|
||||
|
||||
choice KERNEL_IPQ_MEM_PROFILE
|
||||
prompt "IPQ memory profile"
|
||||
default IPQ_MEM_PROFILE_1024
|
||||
|
||||
config IPQ_MEM_PROFILE_1024
|
||||
bool "1024"
|
||||
config IPQ_MEM_PROFILE_512
|
||||
bool "512"
|
||||
config IPQ_MEM_PROFILE_256
|
||||
bool "256"
|
||||
endchoice
|
||||
|
||||
config KERNEL_IPQ_MEM_PROFILE
|
||||
int
|
||||
default 1024 if IPQ_MEM_PROFILE_1024
|
||||
default 512 if IPQ_MEM_PROFILE_512
|
||||
default 256 if IPQ_MEM_PROFILE_256
|
||||
|
||||
help
|
||||
This option select memory profile to used, which defines
|
||||
the reserved memory configuration used in device tree
|
||||
|
||||
config KERNEL_SKB_RECYCLER
|
||||
bool "Generic SKB recycling"
|
||||
default y if KERNEL_IPQ_MEM_PROFILE > 256
|
||||
|
||||
choice KERNEL_SKB_RECYCLE_SIZE
|
||||
prompt "SKB recycler size"
|
||||
default SKB_RECYCLE_SIZE_2304
|
||||
default SKB_RECYCLE_SIZE_1856 if KERNEL_IPQ_MEM_PROFILE < 1024
|
||||
|
||||
depends on KERNEL_SKB_RECYCLER
|
||||
config SKB_RECYCLE_SIZE_1856
|
||||
bool "1856"
|
||||
config SKB_RECYCLE_SIZE_2304
|
||||
bool "2304"
|
||||
endchoice
|
||||
|
||||
config KERNEL_SKB_RECYCLE_SIZE
|
||||
int
|
||||
depends on KERNEL_SKB_RECYCLER
|
||||
default 2304 if SKB_RECYCLE_SIZE_2304
|
||||
default 1856 if SKB_RECYCLE_SIZE_1856
|
||||
|
||||
help
|
||||
SKB recycler default size
|
||||
|
||||
config KERNEL_SKB_RECYCLER_MULTI_CPU
|
||||
bool "Cross-CPU recycling for CPU-locked workloads"
|
||||
depends on KERNEL_SKB_RECYCLER
|
||||
default y
|
||||
|
||||
config KERNEL_SKB_RECYCLER_PREALLOC
|
||||
bool "Enable preallocation of SKBs (For SFE not NSS)"
|
||||
depends on KERNEL_SKB_RECYCLER
|
||||
default n
|
||||
help
|
||||
NOTE: This is primarily for platforms utilizing SFE (Shortcut Forwarding Engine)
|
||||
and not NSS (Network Subsystem) offload.
|
||||
|
||||
NSS offload platforms mostly utilize the SKB recycling feature when managing memory.
|
||||
Mostly when to "reclaim" it.
|
||||
|
||||
This option enables preallocation of SKBs.
|
||||
The default is '16384' which means 16384 x 4096 (Size of SKB) = 64MB.
|
||||
|
||||
config KERNEL_SKB_RECYCLE_MAX_PREALLOC_SKBS
|
||||
int "Number of SKBs to be preallocated"
|
||||
depends on KERNEL_SKB_RECYCLER_PREALLOC
|
||||
default 16384
|
||||
|
||||
config KERNEL_SKB_FIXED_SIZE_2K
|
||||
bool "SKB size fixed at 2K"
|
||||
default n
|
||||
default y if KERNEL_IPQ_MEM_PROFILE < 512
|
||||
help
|
||||
SKB size fixed at 2K. Primarily for platforms with less than 512MB memory.
|
||||
|
||||
config KERNEL_ALLOC_SKB_PAGE_FRAG_DISABLE
|
||||
depends on KERNEL_SKB_RECYCLER
|
||||
bool "Disable alloc skb page frag"
|
||||
default n
|
||||
|
||||
choice KERNEL_PREEMPTION
|
||||
prompt "Kernel preemption level"
|
||||
default KERNEL_PREEMPT
|
||||
|
||||
config KERNEL_PREEMPT_NONE
|
||||
bool "No Forced Preemption (Server)"
|
||||
help
|
||||
This is the traditional Linux preemption model, geared towards
|
||||
throughput. It will still provide good latencies most of the time,
|
||||
but there are no guarantees and occasional longer delays are
|
||||
possible.
|
||||
|
||||
Select this option if you are building a kernel for a server or
|
||||
scientific/computation system, or if you want to maximize the
|
||||
raw processing power of the kernel, irrespective of scheduling
|
||||
latencies.
|
||||
|
||||
config KERNEL_PREEMPT_NONE_BUILD
|
||||
depends on KERNEL_PREEMPT_NONE
|
||||
bool
|
||||
default y
|
||||
|
||||
config KERNEL_PREEMPT
|
||||
bool "Preemptible Kernel (Low-Latency)"
|
||||
help
|
||||
This option reduces the latency of the kernel by making
|
||||
all kernel code (that is not executing in a critical section)
|
||||
preemptible. This allows reaction to interactive events by
|
||||
permitting a low priority process to be preempted involuntarily
|
||||
even if it is in kernel mode executing a system call and would
|
||||
otherwise not be about to reach a natural preemption point.
|
||||
This allows applications to run more 'smoothly' even when the
|
||||
system is under load, at the cost of slightly lower throughput
|
||||
and a slight runtime overhead to kernel code.
|
||||
|
||||
Select this if you are building a kernel for a desktop or
|
||||
embedded system with latency requirements in the milliseconds
|
||||
range.
|
||||
|
||||
if KERNEL_PREEMPT
|
||||
config KERNEL_PREEMPT_RCU
|
||||
bool "Preemptible RCU"
|
||||
default y
|
||||
select KERNEL_PREEMPT_COUNT
|
||||
help
|
||||
This option selects the RCU implementation that is
|
||||
designed for very large SMP systems with hundreds or
|
||||
thousands of CPUs, but for which real-time response
|
||||
is also required. It also scales down nicely to
|
||||
smaller systems.
|
||||
|
||||
Select this option if you are unsure.
|
||||
|
||||
endif
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
@ -1,3 +1,5 @@
|
||||
src-git nss_packages https://github.com/qosmio/nss-packages.git
|
||||
src-git sqm_scripts_nss https://github.com/qosmio/sqm-scripts-nss.git
|
||||
src-git packages https://github.com/immortalwrt/packages.git
|
||||
src-git luci https://github.com/immortalwrt/luci.git
|
||||
src-git routing https://github.com/openwrt/routing.git
|
||||
|
||||
@ -312,8 +312,8 @@ generate_static_system() {
|
||||
delete system.@system[0]
|
||||
add system system
|
||||
set system.@system[-1].hostname='ImmortalWrt'
|
||||
set system.@system[-1].timezone='GMT0'
|
||||
set system.@system[-1].zonename='UTC'
|
||||
set system.@system[-1].timezone="CST-8"
|
||||
set system.@system[-1].zonename="Asia/Shanghai"
|
||||
set system.@system[-1].ttylogin='0'
|
||||
set system.@system[-1].log_size='128'
|
||||
set system.@system[-1].urandom_seed='0'
|
||||
@ -322,10 +322,10 @@ generate_static_system() {
|
||||
set system.ntp='timeserver'
|
||||
set system.ntp.enabled='1'
|
||||
set system.ntp.enable_server='0'
|
||||
add_list system.ntp.server='time1.apple.com'
|
||||
add_list system.ntp.server='time1.google.com'
|
||||
add_list system.ntp.server='time.cloudflare.com'
|
||||
add_list system.ntp.server='pool.ntp.org'
|
||||
add_list system.ntp.server="ntp.tencent.com"
|
||||
add_list system.ntp.server="ntp.aliyun.com"
|
||||
add_list system.ntp.server="ntp.ntsc.ac.cn"
|
||||
add_list system.ntp.server="cn.ntp.org.cn"
|
||||
EOF
|
||||
|
||||
if json_is_a system object; then
|
||||
|
||||
0
package/base-files/files/etc/board.d/99-default_network
Normal file → Executable file
0
package/base-files/files/etc/board.d/99-default_network
Normal file → Executable file
0
package/base-files/files/etc/hotplug.d/leds/00-init
Normal file → Executable file
0
package/base-files/files/etc/hotplug.d/leds/00-init
Normal file → Executable file
0
package/base-files/files/etc/hotplug.d/net/00-sysctl
Normal file → Executable file
0
package/base-files/files/etc/hotplug.d/net/00-sysctl
Normal file → Executable file
0
package/base-files/files/etc/sysctl.d/10-default.conf
Normal file → Executable file
0
package/base-files/files/etc/sysctl.d/10-default.conf
Normal file → Executable file
0
package/base-files/files/etc/uci-defaults/10_migrate-shadow
Normal file → Executable file
0
package/base-files/files/etc/uci-defaults/10_migrate-shadow
Normal file → Executable file
0
package/base-files/files/etc/uci-defaults/11_network-migrate-bridges
Normal file → Executable file
0
package/base-files/files/etc/uci-defaults/11_network-migrate-bridges
Normal file → Executable file
0
package/base-files/files/etc/uci-defaults/12_network-generate-ula
Normal file → Executable file
0
package/base-files/files/etc/uci-defaults/12_network-generate-ula
Normal file → Executable file
0
package/base-files/files/etc/uci-defaults/13_fix-group-user
Normal file → Executable file
0
package/base-files/files/etc/uci-defaults/13_fix-group-user
Normal file → Executable file
0
package/base-files/files/etc/uci-defaults/50-root-passwd
Normal file → Executable file
0
package/base-files/files/etc/uci-defaults/50-root-passwd
Normal file → Executable file
@ -1,5 +1,4 @@
|
||||
# Copyright (C) 2021 OpenWrt.org
|
||||
#
|
||||
|
||||
. /lib/functions.sh
|
||||
|
||||
@ -29,8 +28,7 @@ emmc_upgrade_tar() {
|
||||
sync
|
||||
}
|
||||
|
||||
[ "$has_kernel" = 1 -a "$EMMC_KERN_DEV" ] &&
|
||||
export EMMC_KERNEL_BLOCKS=$(($(tar xf "$tar_file" ${board_dir}/kernel -O | dd of="$EMMC_KERN_DEV" bs=512 2>&1 | grep "records out" | cut -d' ' -f1)))
|
||||
[ "$has_kernel" = 1 -a "$EMMC_KERN_DEV" ] && export EMMC_KERNEL_BLOCKS=$(($(tar xf "$tar_file" ${board_dir}/kernel -O | dd of="$EMMC_KERN_DEV" bs=512 2>&1 | grep "records out" | cut -d' ' -f1)))
|
||||
|
||||
if [ -z "$UPGRADE_BACKUP" ]; then
|
||||
if [ "$EMMC_DATA_DEV" ]; then
|
||||
|
||||
@ -7,13 +7,29 @@ touch /etc/config/ubootenv
|
||||
|
||||
board=$(board_name)
|
||||
|
||||
ubootenv_add_mtd() {
|
||||
local idx="$(find_mtd_index "${1}")"
|
||||
[ -n "$idx" ] && ubootenv_add_uci_config "/dev/mtd$idx" "${2}" "${3}" "${4}"
|
||||
}
|
||||
|
||||
ubootenv_add_sys_mtd() {
|
||||
local idx="$(find_mtd_index "${1}")"
|
||||
[ -n "$idx" ] && ubootenv_add_uci_sys_config "/dev/mtd$idx" "${2}" "${3}" "${4}"
|
||||
}
|
||||
|
||||
ubootenv_add_mmc() {
|
||||
local mmcpart="$(find_mmc_part "${1}")"
|
||||
[ -n "$mmcpart" ] && ubootenv_add_uci_config "$mmcpart" "${2}" "${3}" "${4}" "${5}"
|
||||
}
|
||||
|
||||
case "$board" in
|
||||
linksys,mx2000|\
|
||||
linksys,mx5500|\
|
||||
linksys,spnmx56)
|
||||
idx="$(find_mtd_index u_env)"
|
||||
[ -n "$idx" ] && \
|
||||
ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x40000" "0x20000"
|
||||
ubootenv_add_mtd "/dev/mtd$idx" "0x0" "0x40000" "0x20000"
|
||||
;;
|
||||
jdcloud,re-cs-03)
|
||||
ubootenv_add_mmc "0:APPSBLENV" "0x0" "0x40000" "0x20000"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
@ -9,8 +9,17 @@ board=$(board_name)
|
||||
|
||||
ubootenv_add_mtd() {
|
||||
local idx="$(find_mtd_index "${1}")"
|
||||
[ -n "$idx" ] && \
|
||||
ubootenv_add_uci_config "/dev/mtd$idx" "${2}" "${3}" "${4}"
|
||||
[ -n "$idx" ] && ubootenv_add_uci_config "/dev/mtd$idx" "${2}" "${3}" "${4}"
|
||||
}
|
||||
|
||||
ubootenv_add_sys_mtd() {
|
||||
local idx="$(find_mtd_index "${1}")"
|
||||
[ -n "$idx" ] && ubootenv_add_uci_sys_config "/dev/mtd$idx" "${2}" "${3}" "${4}"
|
||||
}
|
||||
|
||||
ubootenv_add_mmc() {
|
||||
local mmcpart="$(find_mmc_part "${1}")"
|
||||
[ -n "$mmcpart" ] && ubootenv_add_uci_config "$mmcpart" "${2}" "${3}" "${4}" "${5}"
|
||||
}
|
||||
|
||||
case "$board" in
|
||||
@ -22,6 +31,13 @@ cambiumnetworks,xe3-4)
|
||||
linksys,mr7350)
|
||||
ubootenv_add_mtd "u_env" "0x0" "0x40000" "0x20000"
|
||||
;;
|
||||
cmiot,ax18|\
|
||||
glinet,gl-ax1800|\
|
||||
glinet,gl-axt1800|\
|
||||
qihoo,360v6|\
|
||||
redmi,ax5|\
|
||||
xiaomi,ax1800|\
|
||||
zn,m2|\
|
||||
netgear,wax214|\
|
||||
tplink,eap610-outdoor)
|
||||
ubootenv_add_mtd "0:appsblenv" "0x0" "0x40000" "0x20000"
|
||||
@ -29,6 +45,14 @@ tplink,eap610-outdoor)
|
||||
yuncore,fap650)
|
||||
ubootenv_add_mtd "0:appsblenv" "0x0" "0x10000" "0x10000"
|
||||
;;
|
||||
jdcloud,re-ss-01|\
|
||||
jdcloud,re-cs-02|\
|
||||
jdcloud,re-cs-07|\
|
||||
link,nn6000-v1|\
|
||||
link,nn6000-v2|\
|
||||
redmi,ax5-jdcloud)
|
||||
ubootenv_add_mmc "0:APPSBLENV" "0x0" "0x40000" "0x20000"
|
||||
;;
|
||||
esac
|
||||
|
||||
config_load ubootenv
|
||||
|
||||
@ -9,20 +9,17 @@ board=$(board_name)
|
||||
|
||||
ubootenv_add_mtd() {
|
||||
local idx="$(find_mtd_index "${1}")"
|
||||
[ -n "$idx" ] && \
|
||||
ubootenv_add_uci_config "/dev/mtd$idx" "${2}" "${3}" "${4}"
|
||||
[ -n "$idx" ] && ubootenv_add_uci_config "/dev/mtd$idx" "${2}" "${3}" "${4}"
|
||||
}
|
||||
|
||||
ubootenv_add_sys_mtd() {
|
||||
local idx="$(find_mtd_index "${1}")"
|
||||
[ -n "$idx" ] && \
|
||||
ubootenv_add_uci_sys_config "/dev/mtd$idx" "${2}" "${3}" "${4}"
|
||||
[ -n "$idx" ] && ubootenv_add_uci_sys_config "/dev/mtd$idx" "${2}" "${3}" "${4}"
|
||||
}
|
||||
|
||||
ubootenv_add_mmc() {
|
||||
local mmcpart="$(find_mmc_part "${1}")"
|
||||
[ -n "$mmcpart" ] && \
|
||||
ubootenv_add_uci_config "$mmcpart" "${2}" "${3}" "${4}" "${5}"
|
||||
[ -n "$mmcpart" ] && ubootenv_add_uci_config "$mmcpart" "${2}" "${3}" "${4}" "${5}"
|
||||
}
|
||||
|
||||
case "$board" in
|
||||
@ -74,8 +71,9 @@ asus,rt-ax89x|\
|
||||
qnap,301w)
|
||||
ubootenv_add_mtd "0:appsblenv" "0x0" "0x20000" "0x20000"
|
||||
;;
|
||||
spectrum,sax1v1k)
|
||||
ubootenv_add_mmc "0:APPSBLENV" "0x0" "0x40000" "0x40000" "1"
|
||||
spectrum,sax1v1k|\
|
||||
verizon,cr1000a)
|
||||
ubootenv_add_mmc "0:APPSBLENV" "0x0" "0x40000" "0x40000"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
@ -30,8 +30,6 @@ define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/autocore/install
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_BIN) ./files/60-autocore-reload-rpcd $(1)/etc/uci-defaults/
|
||||
|
||||
ifneq ($(filter i386 i686 x86_64, $(ARCH)),)
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
/etc/init.d/rpcd restart
|
||||
|
||||
exit 0
|
||||
0
package/emortal/autocore/files/luci-mod-status-autocore.json
Normal file → Executable file
0
package/emortal/autocore/files/luci-mod-status-autocore.json
Normal file → Executable file
@ -7,25 +7,25 @@ THERMAL_PATH="/sys/class/thermal"
|
||||
|
||||
case "$DISTRIB_TARGET" in
|
||||
ipq40xx/*|ipq806x/*)
|
||||
wifi_temp="$(awk '{printf("%.1f°C ", $0 / 1000)}' "$IEEE_PATH"/phy*/device/hwmon/hwmon*/temp1_input 2>"/dev/null" | awk '$1=$1')"
|
||||
wifi_temp="$(cat "$IEEE_PATH"/phy*/device/hwmon/hwmon*/temp1_input 2>"/dev/null" | awk '{printf("%.1f°C ", $0 / 1000)}' | awk '$1=$1')"
|
||||
;;
|
||||
mediatek/mt7622)
|
||||
wifi_temp="$(awk '{printf("%.1f°C ", $0 / 1000)}' "$IEEE_PATH"/wl*/hwmon*/temp1_input 2>"/dev/null" | awk '$1=$1')"
|
||||
wifi_temp="$(cat "$IEEE_PATH"/wl*/hwmon*/temp1_input 2>"/dev/null" | awk '{printf("%.1f°C ", $0 / 1000)}' | awk '$1=$1')"
|
||||
;;
|
||||
*)
|
||||
wifi_temp="$(awk '{printf("%.1f°C ", $0 / 1000)}' "$IEEE_PATH"/phy*/hwmon*/temp1_input 2>"/dev/null" | awk '$1=$1')"
|
||||
wifi_temp="$(cat "$IEEE_PATH"/phy*/hwmon*/temp1_input 2>"/dev/null" | awk '{printf("%.1f°C ", $0 / 1000)}' | awk '$1=$1')"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$DISTRIB_TARGET" in
|
||||
ipq40xx/*)
|
||||
if [ -e "$IEEE_PATH/phy0/hwmon0/temp1_input" ]; then
|
||||
mt76_temp="$(awk -F ': ' '{print $2}' "$IEEE_PATH/phy0/hwmon0/temp1_input" 2>"/dev/null")°C"
|
||||
mt76_temp="$(awk -F ': ' '{print $2}' "$IEEE_PATH"/phy0/hwmon0/temp1_input 2>"/dev/null")°C"
|
||||
fi
|
||||
[ -z "$mt76_temp" ] || wifi_temp="${wifi_temp:+$wifi_temp }$mt76_temp"
|
||||
;;
|
||||
*)
|
||||
cpu_temp="$(awk '{printf("%.1f°C", $0 / 1000)}' "$THERMAL_PATH/thermal_zone0/temp" 2>"/dev/null")"
|
||||
cpu_temp="$(cat "$THERMAL_PATH"/thermal_zone0/temp 2>"/dev/null" | awk '{printf("%.1f°C", $0 / 1000)}')"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2010-2011 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=autosamba
|
||||
PKG_VERSION:=1
|
||||
PKG_RELEASE:=12
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/autosamba
|
||||
TITLE:=Samba autoconfig hotplug script.
|
||||
MAINTAINER:=Lean
|
||||
DEPENDS:=+luci-app-samba4 +wsdd2
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/autosamba/description
|
||||
A hotplug script to config Samba share automatically.
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/autosamba/install
|
||||
$(INSTALL_DIR) $(1)/etc/hotplug.d/block
|
||||
$(INSTALL_BIN) ./files/20-smb $(1)/etc/hotplug.d/block/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,autosamba))
|
||||
@ -1,106 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# D-Team Technology Co.,Ltd. ShenZhen
|
||||
# 作者:Vic
|
||||
#
|
||||
# 警告:对着屏幕的哥们,我们允许你使用此脚本,但不允许你抹去作者的信息,请保留这段话。
|
||||
#
|
||||
|
||||
. /lib/functions.sh
|
||||
. /lib/functions/service.sh
|
||||
|
||||
global=0
|
||||
config_file="/etc/config/samba4"
|
||||
|
||||
wait_for_init() {
|
||||
for i in `seq 30`
|
||||
do
|
||||
[ -e /tmp/procd.done ] || {
|
||||
sleep 1; continue;
|
||||
}
|
||||
return
|
||||
done
|
||||
}
|
||||
|
||||
smb_handle() {
|
||||
config_get path $1 path
|
||||
if [ "$path" = "$2" ] ;then
|
||||
global=1
|
||||
fi
|
||||
}
|
||||
|
||||
chk_en() {
|
||||
config_get_bool autoshare $1 autoshare 1
|
||||
[ $autoshare -eq 0 ] && exit
|
||||
}
|
||||
|
||||
config_load samba4
|
||||
config_foreach chk_en samba4
|
||||
|
||||
device=`basename $DEVPATH`
|
||||
|
||||
case "$ACTION" in
|
||||
add)
|
||||
|
||||
case "$device" in
|
||||
sd*);;
|
||||
md*);;
|
||||
hd*);;
|
||||
mmcblk*);;
|
||||
*) return;;
|
||||
esac
|
||||
|
||||
path="/dev/$device"
|
||||
|
||||
wait_for_init
|
||||
|
||||
cat /proc/mounts | grep -v '/boot\|/opt' | while read j
|
||||
do
|
||||
str=${j%% *}
|
||||
if [ "$str" == $path ];then
|
||||
strr=${j#* }
|
||||
target=${strr%% *}
|
||||
global=0
|
||||
config_foreach smb_handle sambashare $target
|
||||
name=${target#*/mnt/}
|
||||
|
||||
if [ $global -eq 0 ] ;then
|
||||
echo -e "\n\nconfig sambashare" >> $config_file
|
||||
echo -e "\toption auto '1'" >> $config_file
|
||||
echo -e "\toption name '$name'" >> $config_file
|
||||
echo -e "\toption path '$target'" >> $config_file
|
||||
echo -e "\toption read_only 'no'" >> $config_file
|
||||
echo -e "\toption guest_ok 'yes'" >> $config_file
|
||||
echo -e "\toption create_mask '0666'" >> $config_file
|
||||
echo -e "\toption dir_mask '0777'" >> $config_file
|
||||
echo -e "\toption device '$device'" >> $config_file
|
||||
echo -e "\toption inherit_owner 'yes'" >> $config_file
|
||||
/etc/init.d/samba4 reload
|
||||
return
|
||||
fi
|
||||
fi
|
||||
done
|
||||
;;
|
||||
|
||||
remove)
|
||||
i=0
|
||||
while true
|
||||
do
|
||||
dev=`uci get samba4.@sambashare[$i].device`
|
||||
[ $? -ne 0 ] && break
|
||||
|
||||
[ "$dev" = "$device" ] && {
|
||||
auto=`uci get samba4.@sambashare[$i].auto`
|
||||
[ $auto = "1" ] && {
|
||||
mount_dir=`uci get samba4.@sambashare[$i].name`
|
||||
uci delete samba4.@sambashare[$i]
|
||||
uci commit
|
||||
/etc/init.d/samba4 reload
|
||||
return
|
||||
}
|
||||
}
|
||||
let i+=1
|
||||
done
|
||||
;;
|
||||
esac
|
||||
@ -9,7 +9,7 @@ if ! uci -q get system.@imm_init[0].system_chn > "/dev/null"; then
|
||||
|
||||
delete system.ntp.server
|
||||
add_list system.ntp.server="ntp.tencent.com"
|
||||
add_list system.ntp.server="ntp1.aliyun.com"
|
||||
add_list system.ntp.server="ntp.aliyun.com"
|
||||
add_list system.ntp.server="ntp.ntsc.ac.cn"
|
||||
add_list system.ntp.server="cn.ntp.org.cn"
|
||||
|
||||
|
||||
36
package/emortal/luci-app-athena-led/.gitignore
vendored
Normal file
36
package/emortal/luci-app-athena-led/.gitignore
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
# 忽略编译生成的文件
|
||||
*.o
|
||||
*.so
|
||||
*.a
|
||||
|
||||
# LuCI 的生成文件和缓存
|
||||
build/
|
||||
bin/
|
||||
.tmp/
|
||||
|
||||
# 忽略 OpenWrt 编译生成的安装包
|
||||
*.ipk
|
||||
*.tar.gz
|
||||
*.deb
|
||||
|
||||
# 忽略临时文件和编辑器缓存
|
||||
*.swp
|
||||
*.swo
|
||||
*.bak
|
||||
*.tmp
|
||||
*.log
|
||||
.DS_Store
|
||||
|
||||
# 忽略 Git 操作时产生的临时文件
|
||||
.git/
|
||||
|
||||
# IDE 配置文件
|
||||
.vscode/
|
||||
.idea/
|
||||
|
||||
# 忽略 Makefile 生成的中间文件
|
||||
/feeds
|
||||
/staging_dir
|
||||
/tmp/
|
||||
config.log
|
||||
config.status
|
||||
1
package/emortal/luci-app-athena-led/.latest_commit
Normal file
1
package/emortal/luci-app-athena-led/.latest_commit
Normal file
@ -0,0 +1 @@
|
||||
f8eeb311
|
||||
43
package/emortal/luci-app-athena-led/Makefile
Normal file
43
package/emortal/luci-app-athena-led/Makefile
Normal file
@ -0,0 +1,43 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-athena-led
|
||||
PKG_DEPENDS:=
|
||||
PKG_VERSION:=0.0.7
|
||||
PKG_RELEASE:=20241029
|
||||
|
||||
LUCI_TITLE:=LuCI Support for athena-led
|
||||
LUCI_DEPENDS:=
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
# 包定义;指示我们的包将如何以及在哪里出现在整体配置菜单中 ('make menuconfig')
|
||||
define Package/$(PKG_NAME)
|
||||
TITLE:=$(PKG_NAME)
|
||||
endef
|
||||
|
||||
# Package description; a more verbose description on what our package does
|
||||
define Package/$(PKG_NAME)/description
|
||||
LuCI support for athenaLed
|
||||
endef
|
||||
|
||||
|
||||
define Package/$(PKG_NAME)/install
|
||||
$(INSTALL_DIR) $(1)/usr/lib/lua/luci
|
||||
cp -pR ./luasrc/* $(1)/usr/lib/lua/luci
|
||||
$(INSTALL_DIR) $(1)/
|
||||
cp -pR ./root/* $(1)/
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/postinst
|
||||
#!/bin/sh
|
||||
chmod +x /usr/sbin/athena-led
|
||||
chmod +x /etc/init.d/athena_led
|
||||
exit 0
|
||||
endef
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# This command is always the last, it uses the definitions and variables we give above in order to get the job done
|
||||
$(eval $(call BuildPackage,$(PKG_NAME)))
|
||||
|
||||
|
||||
21
package/emortal/luci-app-athena-led/README.md
Normal file
21
package/emortal/luci-app-athena-led/README.md
Normal file
@ -0,0 +1,21 @@
|
||||
# luci-app-athena-led
|
||||
jdCloud ax6600 led screen ctrl
|
||||
|
||||
#### 定时关闭开启代码
|
||||
|
||||
```
|
||||
# 早上9点30开启显示
|
||||
30 9 * * * uci set athena_led.config.enable='1' && uci commit athena_led && /etc/init.d/athena_led reload
|
||||
# 下午6点30关闭显示
|
||||
30 18 * * * uci set athena_led.config.enable='0' && uci commit athena_led && /etc/init.d/athena_led reload
|
||||
```
|
||||
|
||||
[推荐固件下载地址](https://github.com/VIKINGYFY/OpenWRT-CI/releases)
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
感谢以下朋友的捐赠
|
||||
1. *姆
|
||||
@ -0,0 +1,18 @@
|
||||
module("luci.controller.athena_led", package.seeall)
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/athena_led") then
|
||||
return
|
||||
end
|
||||
entry({ "admin", "system", "athena_led" }, firstchild(), _("Athena LED Ctrl"), 80).dependent = false
|
||||
entry({ "admin", "system", "athena_led", "general" }, cbi("athena_led/settings"), _("Base Setting"), 1)
|
||||
|
||||
entry({ "admin", "system", "athena_led", "status" }, call("act_status"))
|
||||
end
|
||||
|
||||
function act_status()
|
||||
local e = {}
|
||||
e.running = luci.sys.call("pgrep /usr/sbin/athena-led >/dev/null") == 0
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
@ -0,0 +1,84 @@
|
||||
m = Map("athena_led", translate("Athena led Ctrl"), translate("JDCloud AX6600 LED Screen Ctrl"))
|
||||
|
||||
m:section(SimpleSection).template = "athena_led/athena_led_status"
|
||||
|
||||
s = m:section(TypedSection, "athena_led")
|
||||
s.addremove = false
|
||||
s.anonymous = true
|
||||
|
||||
enable = s:option(Flag, "enable", translate("Enabled"))
|
||||
enable.rmempty = false
|
||||
|
||||
seconds = s:option(ListValue, "seconds", translate("Display interval time"))
|
||||
seconds.default = "5"
|
||||
seconds.rmempty = false
|
||||
seconds:value("1")
|
||||
seconds:value("2")
|
||||
seconds:value("3")
|
||||
seconds:value("4")
|
||||
seconds:value("5")
|
||||
seconds.description = translate("Enable carousel display and set interval time in seconds")
|
||||
|
||||
seconds = s:option(ListValue, "lightLevel", translate("Display light level"))
|
||||
seconds.default = "5"
|
||||
seconds.rmempty = false
|
||||
seconds:value("0")
|
||||
seconds:value("1")
|
||||
seconds:value("2")
|
||||
seconds:value("3")
|
||||
seconds:value("4")
|
||||
seconds:value("5")
|
||||
seconds:value("6")
|
||||
seconds:value("7")
|
||||
seconds.description = translate("Display light level desc")
|
||||
|
||||
status = s:option(MultiValue, "status", translate("side led status"))
|
||||
status.default = ""
|
||||
status.rmempty = true
|
||||
status:value("time", translate("status time"))
|
||||
status:value("medal", translate("status medal"))
|
||||
status:value("upload", translate("status upload"))
|
||||
status:value("download", translate("status download"))
|
||||
status.description = translate("side led status desc")
|
||||
|
||||
type = s:option(MultiValue, "option", translate("Display Type"))
|
||||
type.default = "date timeBlink"
|
||||
type.rmempty = false
|
||||
type:value("date", translate("Display Type Date"))
|
||||
type:value("time", translate("Display Type Time"))
|
||||
type:value("timeBlink", translate("Display Type Time Blink"))
|
||||
type:value("temp", translate("Display Type temp"))
|
||||
type:value("string", translate("Display Type String"))
|
||||
type:value("getByUrl", translate("Display Type getByUrl"))
|
||||
type.description = translate("Specify comma-separated values for option")
|
||||
|
||||
customValue = s:option(Value, "value", translate("Custom Value"))
|
||||
customValue.default = "abcdefghijklmnopqrstuvwxyz0123456789+-*/=.::℃"
|
||||
customValue.rmempty = false
|
||||
customValue.placeholder = translate("Enter your message here")
|
||||
customValue.description = translate("Set the custom message to display on the LED screen, Only effective on 'Display Type String'")
|
||||
|
||||
url = s:option(Value, "url", translate("api url for get content"))
|
||||
url.default = "http://www.baidu.com"
|
||||
url.rmempty = false
|
||||
url.placeholder = translate("Enter your api url here")
|
||||
url.description = translate("api url for get content des")
|
||||
|
||||
tempFlag = s:option(MultiValue, "tempFlag", translate("tempFlag"))
|
||||
tempFlag.default = "4"
|
||||
tempFlag.rmempty = false
|
||||
tempFlag:value("0", translate("nss-top"))
|
||||
tempFlag:value("1", translate("nss"))
|
||||
tempFlag:value("2", translate("wcss-phya0"))
|
||||
tempFlag:value("3", translate("wcss-phya1"))
|
||||
tempFlag:value("4", translate("cpu"))
|
||||
tempFlag:value("5", translate("lpass"))
|
||||
tempFlag:value("6", translate("ddrss"))
|
||||
tempFlag.description = translate("Set the item display on the LED screen, Only effective on 'Display Type temp'")
|
||||
|
||||
function m.on_after_commit(self)
|
||||
local output = luci.util.exec("/etc/init.d/athena_led reload >/dev/null 2>&1")
|
||||
luci.util.exec("logger '" .. output .. "'")
|
||||
end
|
||||
|
||||
return m
|
||||
@ -0,0 +1,25 @@
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
XHR.poll(3, '<%=url([[admin]], [[system]], [[athena_led]], [[status]])%>', null,
|
||||
function (x, data) {
|
||||
var tb = document.getElementById('athena_led_status');
|
||||
if (data && tb) {
|
||||
if (data.running) {
|
||||
var links = '<em><b><font color=green>led <%:RUNNING%></font></b></em>';
|
||||
tb.innerHTML = links;
|
||||
} else {
|
||||
tb.innerHTML = '<em><b><font color=red>led <%:NOT RUNNING%></font></b></em>';
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
//]]>
|
||||
</script>
|
||||
<style>.mar-10 {
|
||||
margin-left: 50px;
|
||||
margin-right: 10px;
|
||||
}</style>
|
||||
<fieldset class="cbi-section">
|
||||
<p id="athena_led_status">
|
||||
<em><%:Collecting data...%></em>
|
||||
</p>
|
||||
</fieldset>
|
||||
124
package/emortal/luci-app-athena-led/po/zh-cn/athena_led.po
Normal file
124
package/emortal/luci-app-athena-led/po/zh-cn/athena_led.po
Normal file
@ -0,0 +1,124 @@
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||
|
||||
msgid "athena_led"
|
||||
msgstr "athena_led"
|
||||
|
||||
msgid "Base Setting"
|
||||
msgstr "设置"
|
||||
|
||||
msgid "Gift"
|
||||
msgstr "赞赏"
|
||||
|
||||
msgid "Athena LED Ctrl"
|
||||
msgstr "雅典娜 LED 屏幕控制"
|
||||
|
||||
msgid "JDCloud AX6600 LED Screen Ctrl"
|
||||
msgstr "京东云 AX6600 LED 屏幕控制"
|
||||
|
||||
msgid "Enabled"
|
||||
msgstr "启用"
|
||||
|
||||
msgid "Display interval time"
|
||||
msgstr "刷新时间"
|
||||
|
||||
msgid "Enable carousel display and set interval time in seconds"
|
||||
msgstr "刷新时间"
|
||||
|
||||
msgid "Display light level"
|
||||
msgstr "显示亮度调整"
|
||||
|
||||
msgid "Display light level desc"
|
||||
msgstr "显示亮度调整,数字越大越亮"
|
||||
|
||||
msgid "side led status"
|
||||
msgstr "侧边状态灯"
|
||||
|
||||
msgid "status time"
|
||||
msgstr "时间"
|
||||
|
||||
msgid "status medal"
|
||||
msgstr "奖牌"
|
||||
|
||||
msgid "status upload"
|
||||
msgstr "上传"
|
||||
|
||||
msgid "status download"
|
||||
msgstr "下载"
|
||||
|
||||
msgid "side led status desc"
|
||||
msgstr "设置侧边状态灯"
|
||||
|
||||
|
||||
msgid "Display Type"
|
||||
msgstr "显示模式"
|
||||
|
||||
msgid "Display Type Date"
|
||||
msgstr "日期"
|
||||
|
||||
msgid "Display Type Time"
|
||||
msgstr "时间"
|
||||
|
||||
msgid "Display Type Time Blink"
|
||||
msgstr "时间-闪烁"
|
||||
|
||||
msgid "Display Type temp"
|
||||
msgstr "温度"
|
||||
|
||||
msgid "Display Type String"
|
||||
msgstr "自定义文本"
|
||||
|
||||
msgid "Display Type getByUrl"
|
||||
msgstr "远程文本"
|
||||
|
||||
|
||||
msgid "Specify comma-separated values for option"
|
||||
msgstr "显示模式"
|
||||
|
||||
msgid "Custom Value"
|
||||
msgstr "自定义文本"
|
||||
|
||||
msgid "Enter your message here"
|
||||
msgstr "输入你的自定义内容"
|
||||
|
||||
msgid "Set the custom message to display on the LED screen, Only effective on 'Display Type String'"
|
||||
msgstr "设置显示在led屏幕上的自定义内容,选中'自定义文本'显示模式生效"
|
||||
|
||||
msgid "api url for get content"
|
||||
msgstr "通过 http/get 请求获取显示内容"
|
||||
|
||||
msgid "Enter your api url here"
|
||||
msgstr "在此处输入你的接口地址"
|
||||
|
||||
msgid "api url for get content des"
|
||||
msgstr "通过 http/get 请求获取显示内容,选中'远程文本'显示模式生效"
|
||||
|
||||
msgid "All features are free, and tipping is just to buy me a coffee."
|
||||
msgstr "所有功能都免费,打赏只是为了请我喝咖啡"
|
||||
|
||||
msgid "tempFlag"
|
||||
msgstr "温度选项"
|
||||
|
||||
msgid "nss-top"
|
||||
msgstr "网络子系统nss-top"
|
||||
|
||||
msgid "nss"
|
||||
msgstr "网络子系统nss"
|
||||
|
||||
msgid "wcss-phya0"
|
||||
msgstr "无线控制子系统-物理0"
|
||||
|
||||
msgid "wcss-phya1"
|
||||
msgstr "无线控制子系统-物理1"
|
||||
|
||||
msgid "cpu"
|
||||
msgstr "中央处理器cpu"
|
||||
|
||||
msgid "lpass"
|
||||
msgstr "lpass"
|
||||
|
||||
msgid "ddrss"
|
||||
msgstr "内存子系统ddr"
|
||||
|
||||
msgid "Set the item display on the LED screen, Only effective on 'Display Type temp'"
|
||||
msgstr "设置显示在led屏幕上的温度,选中'温度'显示模式生效"
|
||||
124
package/emortal/luci-app-athena-led/po/zh_Hans/athena_led.po
Normal file
124
package/emortal/luci-app-athena-led/po/zh_Hans/athena_led.po
Normal file
@ -0,0 +1,124 @@
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||
|
||||
msgid "athena_led"
|
||||
msgstr "athena_led"
|
||||
|
||||
msgid "Base Setting"
|
||||
msgstr "设置"
|
||||
|
||||
msgid "Gift"
|
||||
msgstr "赞赏"
|
||||
|
||||
msgid "Athena LED Ctrl"
|
||||
msgstr "雅典娜 LED 屏幕控制"
|
||||
|
||||
msgid "JDCloud AX6600 LED Screen Ctrl"
|
||||
msgstr "京东云 AX6600 LED 屏幕控制"
|
||||
|
||||
msgid "Enabled"
|
||||
msgstr "启用"
|
||||
|
||||
msgid "Display interval time"
|
||||
msgstr "刷新时间"
|
||||
|
||||
msgid "Enable carousel display and set interval time in seconds"
|
||||
msgstr "刷新时间"
|
||||
|
||||
msgid "Display light level"
|
||||
msgstr "显示亮度调整"
|
||||
|
||||
msgid "Display light level desc"
|
||||
msgstr "显示亮度调整,数字越大越亮"
|
||||
|
||||
msgid "side led status"
|
||||
msgstr "侧边状态灯"
|
||||
|
||||
msgid "status time"
|
||||
msgstr "时间"
|
||||
|
||||
msgid "status medal"
|
||||
msgstr "奖牌"
|
||||
|
||||
msgid "status upload"
|
||||
msgstr "上传"
|
||||
|
||||
msgid "status download"
|
||||
msgstr "下载"
|
||||
|
||||
msgid "side led status desc"
|
||||
msgstr "设置侧边状态灯"
|
||||
|
||||
|
||||
msgid "Display Type"
|
||||
msgstr "显示模式"
|
||||
|
||||
msgid "Display Type Date"
|
||||
msgstr "日期"
|
||||
|
||||
msgid "Display Type Time"
|
||||
msgstr "时间"
|
||||
|
||||
msgid "Display Type Time Blink"
|
||||
msgstr "时间-闪烁"
|
||||
|
||||
msgid "Display Type temp"
|
||||
msgstr "温度"
|
||||
|
||||
msgid "Display Type String"
|
||||
msgstr "自定义文本"
|
||||
|
||||
msgid "Display Type getByUrl"
|
||||
msgstr "远程文本"
|
||||
|
||||
|
||||
msgid "Specify comma-separated values for option"
|
||||
msgstr "显示模式"
|
||||
|
||||
msgid "Custom Value"
|
||||
msgstr "自定义文本"
|
||||
|
||||
msgid "Enter your message here"
|
||||
msgstr "输入你的自定义内容"
|
||||
|
||||
msgid "Set the custom message to display on the LED screen, Only effective on 'Display Type String'"
|
||||
msgstr "设置显示在led屏幕上的自定义内容,选中'自定义文本'显示模式生效"
|
||||
|
||||
msgid "api url for get content"
|
||||
msgstr "通过 http/get 请求获取显示内容"
|
||||
|
||||
msgid "Enter your api url here"
|
||||
msgstr "在此处输入你的接口地址"
|
||||
|
||||
msgid "api url for get content des"
|
||||
msgstr "通过 http/get 请求获取显示内容,选中'远程文本'显示模式生效"
|
||||
|
||||
msgid "All features are free, and tipping is just to buy me a coffee."
|
||||
msgstr "所有功能都免费,打赏只是为了请我喝咖啡"
|
||||
|
||||
msgid "tempFlag"
|
||||
msgstr "温度选项"
|
||||
|
||||
msgid "nss-top"
|
||||
msgstr "网络子系统nss-top"
|
||||
|
||||
msgid "nss"
|
||||
msgstr "网络子系统nss"
|
||||
|
||||
msgid "wcss-phya0"
|
||||
msgstr "无线控制子系统-物理0"
|
||||
|
||||
msgid "wcss-phya1"
|
||||
msgstr "无线控制子系统-物理1"
|
||||
|
||||
msgid "cpu"
|
||||
msgstr "中央处理器cpu"
|
||||
|
||||
msgid "lpass"
|
||||
msgstr "lpass"
|
||||
|
||||
msgid "ddrss"
|
||||
msgstr "内存子系统ddr"
|
||||
|
||||
msgid "Set the item display on the LED screen, Only effective on 'Display Type temp'"
|
||||
msgstr "设置显示在led屏幕上的温度,选中'温度'显示模式生效"
|
||||
@ -0,0 +1,9 @@
|
||||
config athena_led 'config'
|
||||
option enable '1'
|
||||
option status ' '
|
||||
option seconds '5'
|
||||
option lightLevel '5'
|
||||
option option 'date timeBlink'
|
||||
option value 'abcdefghijklmnopqrstuvwxyz0123456789+-*/=.::℃'
|
||||
option url 'https://www.baidu.com'
|
||||
option tempFlag '4'
|
||||
42
package/emortal/luci-app-athena-led/root/etc/init.d/athena_led
Executable file
42
package/emortal/luci-app-athena-led/root/etc/init.d/athena_led
Executable file
@ -0,0 +1,42 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=99
|
||||
STOP=99
|
||||
USE_PROCD=1
|
||||
PROG=/usr/sbin/athena-led
|
||||
|
||||
start_service() {
|
||||
config_load 'athena_led'
|
||||
local cfg='config'
|
||||
|
||||
config_get_bool enabled "$cfg" 'enable' '0'
|
||||
if [ "$enabled" -eq 0 ]; then
|
||||
logger "athena-led Service is disabled, not starting"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local status seconds lightLevel option value
|
||||
config_get status $cfg 'status' ' '
|
||||
config_get seconds $cfg 'seconds' '5'
|
||||
config_get lightLevel $cfg 'lightLevel' '5'
|
||||
config_get option $cfg 'option' 'date timeBlink'
|
||||
config_get value $cfg 'value' 'abcdefghijklmnopqrstuvwxyz0123456789+-*/=.::℃'
|
||||
config_get url $cfg 'url' 'https://www.baidu.com'
|
||||
config_get tempFlag $cfg 'tempFlag' '4'
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command $PROG -status "${status}" -seconds "${seconds}" -lightLevel "${lightLevel}" -option "${option}" -value "${value}" -url "${url}" -tempFlag "${tempFlag}"
|
||||
procd_set_param respawn
|
||||
procd_close_instance
|
||||
|
||||
}
|
||||
|
||||
service_triggers(){
|
||||
procd_add_reload_trigger "athena_led"
|
||||
}
|
||||
|
||||
reload_service()
|
||||
{
|
||||
stop
|
||||
start
|
||||
}
|
||||
BIN
package/emortal/luci-app-athena-led/root/usr/sbin/athena-led
Executable file
BIN
package/emortal/luci-app-athena-led/root/usr/sbin/athena-led
Executable file
Binary file not shown.
@ -8,13 +8,13 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ath11k-firmware
|
||||
PKG_SOURCE_DATE:=2024-10-14
|
||||
PKG_SOURCE_VERSION:=15f050122da5ef5bef2cc8c7c19dfb7f98060a49
|
||||
PKG_MIRROR_HASH:=e7a89d1570f32552ade539376181494724b5eafb31d00451ff2dcf5a2922a0cb
|
||||
PKG_SOURCE_DATE:=2025-02-20
|
||||
PKG_SOURCE_VERSION:=0407f7b00b4efd79a16a9481b6bfb6292888a52e
|
||||
PKG_MIRROR_HASH:=6b03d8bd7ac37765e055f7d6ee41867ee8c4d3e9825f907e5663ffa9b5e3fcaa
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://git.codelinaro.org/clo/ath-firmware/ath11k-firmware.git
|
||||
PKG_SOURCE_URL:=https://github.com/VIKINGYFY/ath11k-firmware-ddwrt.git
|
||||
|
||||
PKG_LICENSE_FILES:=LICENSE.qca_firmware
|
||||
|
||||
@ -25,21 +25,6 @@ include $(INCLUDE_DIR)/package.mk
|
||||
RSTRIP:=:
|
||||
STRIP:=:
|
||||
|
||||
ATH11K_LEGACY_FW_NAME:=ath11k-legacy-firmware
|
||||
ATH11K_LEGACY_FW_DATE:=2024-03-14
|
||||
ATH11K_LEGACY_FW_RELEASE:=795809c7
|
||||
ATH11K_LEGACY_FW_SUBDIR:=$(ATH11K_LEGACY_FW_NAME)-$(ATH11K_LEGACY_FW_DATE)~$(ATH11K_LEGACY_FW_RELEASE)
|
||||
ATH11K_LEGACY_FW_SOURCE=$(ATH11K_LEGACY_FW_SUBDIR).tar.zst
|
||||
|
||||
define Download/$(ATH11K_LEGACY_FW_NAME)
|
||||
FILE:=$(ATH11K_LEGACY_FW_SOURCE)
|
||||
PROTO:=git
|
||||
URL:=https://github.com/quic/upstream-wifi-fw.git
|
||||
SOURCE_VERSION:=795809c7041582bd51bdfaa1f548b916ae8d4382
|
||||
MIRROR_HASH:=e042024b6762a5b4fe56f1a5bf8870df2e7abcca90ec22103cd46a609bee7cec
|
||||
SUBDIR:=$(ATH11K_LEGACY_FW_SUBDIR)
|
||||
endef
|
||||
|
||||
define Package/ath11k-firmware-default
|
||||
SECTION:=firmware
|
||||
CATEGORY:=Firmware
|
||||
@ -73,60 +58,33 @@ $(Package/ath11k-firmware-default)
|
||||
TITLE:=QCN9074 ath11k firmware
|
||||
endef
|
||||
|
||||
define Build/Clean
|
||||
$(call Build/Clean/Default,)
|
||||
|
||||
rm -rf \
|
||||
$(BUILD_DIR)/$(ATH11K_LEGACY_FW_SUBDIR)
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
$(eval $(call Download,ath11k-legacy-firmware))
|
||||
|
||||
$(call Build/Prepare/Default,)
|
||||
|
||||
$(TAR) -C $(BUILD_DIR) -xf $(DL_DIR)/$(ATH11K_LEGACY_FW_SOURCE)
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
|
||||
endef
|
||||
|
||||
define Package/ath11k-firmware-ipq5018/install
|
||||
$(INSTALL_DIR) $(1)/lib/firmware/ath11k/IPQ5018/hw1.0
|
||||
$(INSTALL_DATA) \
|
||||
$(BUILD_DIR)/$(ATH11K_LEGACY_FW_SUBDIR)/ath11k-firmware/IPQ5018_QCN6122_QCN6122/hw1.0/2.7.0.1/WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1/*.* \
|
||||
$(1)/lib/firmware/ath11k/IPQ5018/hw1.0/
|
||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/IPQ5018/hw1.0/* $(1)/lib/firmware/ath11k/IPQ5018/hw1.0/
|
||||
endef
|
||||
|
||||
define Package/ath11k-firmware-ipq6018/install
|
||||
$(INSTALL_DIR) $(1)/lib/firmware/IPQ6018
|
||||
$(INSTALL_DATA) \
|
||||
$(PKG_BUILD_DIR)/IPQ6018/hw1.0/2.5.0.1/WLAN.HK.2.5.0.1-03982-QCAHKSWPL_SILICONZ-3/* \
|
||||
$(1)/lib/firmware/IPQ6018/
|
||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/IPQ6018/hw1.0/* $(1)/lib/firmware/IPQ6018/
|
||||
endef
|
||||
|
||||
define Package/ath11k-firmware-ipq8074/install
|
||||
$(INSTALL_DIR) $(1)/lib/firmware/IPQ8074
|
||||
$(INSTALL_DATA) \
|
||||
$(PKG_BUILD_DIR)/IPQ8074/hw2.0/2.9.0.1/WLAN.HK.2.9.0.1-02146-QCAHKSWPL_SILICONZ-1/* \
|
||||
$(1)/lib/firmware/IPQ8074/
|
||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/IPQ8074/hw2.0/* $(1)/lib/firmware/IPQ8074/
|
||||
endef
|
||||
|
||||
define Package/ath11k-firmware-qcn6122/install
|
||||
$(INSTALL_DIR) $(1)/lib/firmware/ath11k/QCN6122/hw1.0
|
||||
$(INSTALL_DATA) \
|
||||
$(BUILD_DIR)/$(ATH11K_LEGACY_FW_SUBDIR)/ath11k-firmware/IPQ5018_QCN6122_QCN6122/hw1.0/2.7.0.1/WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1/qcn6122/* \
|
||||
$(1)/lib/firmware/ath11k/QCN6122/hw1.0/
|
||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/QCN6122/hw1.0/* $(1)/lib/firmware/ath11k/QCN6122/hw1.0/
|
||||
endef
|
||||
|
||||
define Package/ath11k-firmware-qcn9074/install
|
||||
$(INSTALL_DIR) $(1)/lib/firmware/ath11k/QCN9074/hw1.0
|
||||
$(INSTALL_DATA) \
|
||||
$(PKG_BUILD_DIR)/QCN9074/hw1.0/2.9.0.1/WLAN.HK.2.9.0.1-02146-QCAHKSWPL_SILICONZ-1/* \
|
||||
$(1)/lib/firmware/ath11k/QCN9074/hw1.0/
|
||||
$(INSTALL_BIN) \
|
||||
$(PKG_BUILD_DIR)/QCN9074/hw1.0/board-2.bin $(1)/lib/firmware/ath11k/QCN9074/hw1.0/board-2.bin
|
||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/QCN9074/hw1.0/* $(1)/lib/firmware/ath11k/QCN9074/hw1.0/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ath11k-firmware-ipq5018))
|
||||
|
||||
@ -73,7 +73,19 @@ ALLWIFIBOARDS:= \
|
||||
zte_mf269 \
|
||||
zte_mf287 \
|
||||
zte_mf287plus \
|
||||
zyxel_nbg7815
|
||||
zyxel_nbg7815 \
|
||||
cmiot_ax18 \
|
||||
glinet_gl-ax1800 \
|
||||
glinet_gl-axt1800 \
|
||||
jdcloud_re-ss-01 \
|
||||
jdcloud_re-cs-02 \
|
||||
jdcloud_re-cs-03 \
|
||||
link_nn6000 \
|
||||
redmi_ax5 \
|
||||
redmi_ax5-jdcloud \
|
||||
verizon_cr1000a \
|
||||
xiaomi_ax1800 \
|
||||
zn_m2
|
||||
|
||||
ALLWIFIPACKAGES:=$(foreach BOARD,$(ALLWIFIBOARDS),ipq-wifi-$(BOARD))
|
||||
|
||||
@ -214,5 +226,17 @@ $(eval $(call generate-ipq-wifi-package,zte_mf269,ZTE MF269))
|
||||
$(eval $(call generate-ipq-wifi-package,zte_mf287,ZTE MF287))
|
||||
$(eval $(call generate-ipq-wifi-package,zte_mf287plus,ZTE MF287Plus))
|
||||
$(eval $(call generate-ipq-wifi-package,zyxel_nbg7815,Zyxel NBG7815))
|
||||
$(eval $(call generate-ipq-wifi-package,cmiot_ax18,CMIOT AX18))
|
||||
$(eval $(call generate-ipq-wifi-package,glinet_gl-ax1800,GL.iNet GL-AX1800))
|
||||
$(eval $(call generate-ipq-wifi-package,glinet_gl-axt1800,GL.iNet GL-AXT1800))
|
||||
$(eval $(call generate-ipq-wifi-package,jdcloud_re-ss-01,JDCloud RE-SS-01))
|
||||
$(eval $(call generate-ipq-wifi-package,jdcloud_re-cs-02,JDCloud RE-CS-02))
|
||||
$(eval $(call generate-ipq-wifi-package,jdcloud_re-cs-03,JDCloud RE-CS-03))
|
||||
$(eval $(call generate-ipq-wifi-package,link_nn6000,Link NN6000))
|
||||
$(eval $(call generate-ipq-wifi-package,redmi_ax5,Redmi AX5))
|
||||
$(eval $(call generate-ipq-wifi-package,redmi_ax5-jdcloud,Redmi AX5 JDCloud))
|
||||
$(eval $(call generate-ipq-wifi-package,verizon_cr1000a,Verizon CR1000A))
|
||||
$(eval $(call generate-ipq-wifi-package,xiaomi_ax1800,Xiaomi AX1800))
|
||||
$(eval $(call generate-ipq-wifi-package,zn_m2,ZN M2))
|
||||
|
||||
$(foreach PACKAGE,$(ALLWIFIPACKAGES),$(eval $(call BuildPackage,$(PACKAGE))))
|
||||
|
||||
BIN
package/firmware/ipq-wifi/src/board-cmiot_ax18.ipq6018
Normal file
BIN
package/firmware/ipq-wifi/src/board-cmiot_ax18.ipq6018
Normal file
Binary file not shown.
BIN
package/firmware/ipq-wifi/src/board-jdcloud_re-cs-02.ipq6018
Normal file
BIN
package/firmware/ipq-wifi/src/board-jdcloud_re-cs-02.ipq6018
Normal file
Binary file not shown.
BIN
package/firmware/ipq-wifi/src/board-jdcloud_re-cs-02.qcn9074
Normal file
BIN
package/firmware/ipq-wifi/src/board-jdcloud_re-cs-02.qcn9074
Normal file
Binary file not shown.
BIN
package/firmware/ipq-wifi/src/board-jdcloud_re-cs-03.ipq5018
Normal file
BIN
package/firmware/ipq-wifi/src/board-jdcloud_re-cs-03.ipq5018
Normal file
Binary file not shown.
BIN
package/firmware/ipq-wifi/src/board-jdcloud_re-cs-03.qcn6122
Normal file
BIN
package/firmware/ipq-wifi/src/board-jdcloud_re-cs-03.qcn6122
Normal file
Binary file not shown.
BIN
package/firmware/ipq-wifi/src/board-jdcloud_re-ss-01.ipq6018
Normal file
BIN
package/firmware/ipq-wifi/src/board-jdcloud_re-ss-01.ipq6018
Normal file
Binary file not shown.
BIN
package/firmware/ipq-wifi/src/board-link_nn6000.ipq6018
Normal file
BIN
package/firmware/ipq-wifi/src/board-link_nn6000.ipq6018
Normal file
Binary file not shown.
BIN
package/firmware/ipq-wifi/src/board-redmi_ax5-jdcloud.ipq6018
Normal file
BIN
package/firmware/ipq-wifi/src/board-redmi_ax5-jdcloud.ipq6018
Normal file
Binary file not shown.
BIN
package/firmware/ipq-wifi/src/board-redmi_ax5.ipq6018
Normal file
BIN
package/firmware/ipq-wifi/src/board-redmi_ax5.ipq6018
Normal file
Binary file not shown.
BIN
package/firmware/ipq-wifi/src/board-verizon_cr1000a.ipq8074
Normal file
BIN
package/firmware/ipq-wifi/src/board-verizon_cr1000a.ipq8074
Normal file
Binary file not shown.
BIN
package/firmware/ipq-wifi/src/board-xiaomi_ax1800.ipq6018
Normal file
BIN
package/firmware/ipq-wifi/src/board-xiaomi_ax1800.ipq6018
Normal file
Binary file not shown.
BIN
package/firmware/ipq-wifi/src/board-zn_m2.ipq6018
Normal file
BIN
package/firmware/ipq-wifi/src/board-zn_m2.ipq6018
Normal file
Binary file not shown.
@ -0,0 +1,20 @@
|
||||
--- a/ath10k-6.10/mac.c
|
||||
+++ b/ath10k-6.10/mac.c
|
||||
@@ -6365,7 +6365,7 @@ static int ath10k_mac_set_txbf_conf(stru
|
||||
ar->wmi.vdev_param->txbf, value);
|
||||
}
|
||||
|
||||
-static void ath10k_update_vif_offload(struct ieee80211_hw *hw,
|
||||
+static int ath10k_update_vif_offload(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath10k_vif *arvif = (void *)vif->drv_priv;
|
||||
@@ -6387,6 +6387,8 @@ static void ath10k_update_vif_offload(st
|
||||
ath10k_warn(ar, "failed to set vdev %i TX encapsulation: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
}
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -0,0 +1,33 @@
|
||||
--- a/ath10k-6.10/pci.c
|
||||
+++ b/ath10k-6.10/pci.c
|
||||
@@ -2285,6 +2285,7 @@ static int ath10k_pci_hif_start(struct a
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif start\n");
|
||||
|
||||
+ dev_set_threaded(ar->napi_dev, true);
|
||||
ath10k_core_napi_enable(ar);
|
||||
|
||||
ath10k_pci_irq_enable(ar);
|
||||
--- a/ath10k-6.10/sdio.c
|
||||
+++ b/ath10k-6.10/sdio.c
|
||||
@@ -1863,6 +1863,7 @@ static int ath10k_sdio_hif_start(struct
|
||||
struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
|
||||
int ret;
|
||||
|
||||
+ dev_set_threaded(&ar->napi_dev, true);
|
||||
ath10k_core_napi_enable(ar);
|
||||
|
||||
/* Sleep 20 ms before HIF interrupts are disabled.
|
||||
--- a/ath10k-6.10/core.c
|
||||
+++ b/ath10k-6.10/core.c
|
||||
@@ -4576,6 +4576,10 @@ struct ath10k *ath10k_core_create(size_t
|
||||
if (!ar->napi_dev)
|
||||
goto err_free_tx_complete;
|
||||
|
||||
+ snprintf(ar->napi_dev->name, sizeof(ar->napi_dev->name), "ath10k_%s",
|
||||
+ wiphy_name(ar->hw->wiphy));
|
||||
+ dev_set_threaded(ar->napi_dev, true);
|
||||
+
|
||||
ret = ath10k_coredump_create(ar);
|
||||
if (ret)
|
||||
goto err_free_netdev;
|
||||
@ -41,13 +41,22 @@ define KernelPackage/cryptodev/description
|
||||
via a "/dev/crypto" device.
|
||||
endef
|
||||
|
||||
ifneq ($(CONFIG_PACKAGE_kmod-crypto-qce),)
|
||||
EXTRA_CFLAGS+=-DQCA
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_PACKAGE_kmod-qca-nss-crypto),)
|
||||
EXTRA_CFLAGS+=-DQCANSS
|
||||
endif
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(MAKE) -C $(PKG_BUILD_DIR) \
|
||||
$(KERNEL_MAKE_FLAGS) \
|
||||
KERNEL_DIR="$(LINUX_DIR)"
|
||||
KERNEL_DIR="$(LINUX_DIR)" \
|
||||
EXTRA_CFLAGS="$(EXTRA_CFLAGS)"
|
||||
endef
|
||||
|
||||
define Build/InstallDev
|
||||
|
||||
@ -0,0 +1,99 @@
|
||||
--- a/ioctl.c
|
||||
+++ b/ioctl.c
|
||||
@@ -829,29 +829,37 @@ static inline void tfm_info_to_alg_info(
|
||||
"%s", crypto_tfm_alg_driver_name(tfm));
|
||||
}
|
||||
|
||||
-#ifndef CRYPTO_ALG_KERN_DRIVER_ONLY
|
||||
+#if defined(QCANSS) || defined(QCA) || defined(MT7621) || defined(MT7622) || defined(LANTIQ) || defined(BCM675X) || defined(BCM49XX) || defined(MT798X)
|
||||
static unsigned int is_known_accelerated(struct crypto_tfm *tfm)
|
||||
{
|
||||
const char *name = crypto_tfm_alg_driver_name(tfm);
|
||||
|
||||
if (name == NULL)
|
||||
- return 1; /* assume accelerated */
|
||||
+ return 0;
|
||||
|
||||
/* look for known crypto engine names */
|
||||
- if (strstr(name, "-talitos") ||
|
||||
- !strncmp(name, "mv-", 3) ||
|
||||
- !strncmp(name, "atmel-", 6) ||
|
||||
- strstr(name, "geode") ||
|
||||
- strstr(name, "hifn") ||
|
||||
- strstr(name, "-ixp4xx") ||
|
||||
- strstr(name, "-omap") ||
|
||||
- strstr(name, "-picoxcell") ||
|
||||
- strstr(name, "-s5p") ||
|
||||
- strstr(name, "-ppc4xx") ||
|
||||
- strstr(name, "-caam") ||
|
||||
- strstr(name, "-n2"))
|
||||
+#if defined(QCANSS)
|
||||
+ if (!strncmp(name, "nss-", 4))
|
||||
return 1;
|
||||
-
|
||||
+#elif defined(QCA)
|
||||
+ if (!strncmp(name, "qcrypto", 7))
|
||||
+ return 1;
|
||||
+#elif defined(MT7621)
|
||||
+ if (strstr(name, "eip93"))
|
||||
+ return 1;
|
||||
+#elif defined(MT7622)
|
||||
+ if (strstr(name, "mtk"))
|
||||
+ return 1;
|
||||
+#elif defined(MT798X)
|
||||
+ if (strstr(name, "safexcel-"))
|
||||
+ return 1;
|
||||
+#elif defined(LANTIQ)
|
||||
+ if (strstr(name, "ltq-crypto"))
|
||||
+ return 1;
|
||||
+#elif defined(BCM675X) || defined(BCM49XX)
|
||||
+ if (strstr(name, "-iproc"))
|
||||
+ return 1;
|
||||
+#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -876,22 +884,22 @@ static int get_session_info(struct fcryp
|
||||
else
|
||||
tfm = crypto_aead_tfm(ses_ptr->cdata.async.as);
|
||||
tfm_info_to_alg_info(&siop->cipher_info, tfm);
|
||||
-#ifdef CRYPTO_ALG_KERN_DRIVER_ONLY
|
||||
- if (tfm->__crt_alg->cra_flags & CRYPTO_ALG_KERN_DRIVER_ONLY)
|
||||
+#if defined(QCANSS) || defined(QCA) || defined(MT7621) || defined(MT7622) || defined(LANTIQ) || defined(BCM675X) || defined(BCM49XX) || defined(MT798X)
|
||||
+ if (is_known_accelerated(tfm))
|
||||
siop->flags |= SIOP_FLAG_KERNEL_DRIVER_ONLY;
|
||||
#else
|
||||
- if (is_known_accelerated(tfm))
|
||||
+ if (tfm->__crt_alg->cra_flags & CRYPTO_ALG_KERN_DRIVER_ONLY)
|
||||
siop->flags |= SIOP_FLAG_KERNEL_DRIVER_ONLY;
|
||||
#endif
|
||||
}
|
||||
if (ses_ptr->hdata.init) {
|
||||
tfm = crypto_ahash_tfm(ses_ptr->hdata.async.s);
|
||||
tfm_info_to_alg_info(&siop->hash_info, tfm);
|
||||
-#ifdef CRYPTO_ALG_KERN_DRIVER_ONLY
|
||||
- if (tfm->__crt_alg->cra_flags & CRYPTO_ALG_KERN_DRIVER_ONLY)
|
||||
+#if defined(QCANSS) || defined(QCA) || defined(MT7621) || defined(MT7622) || defined(LANTIQ) || defined(BCM675X) || defined(BCM49XX) || defined(MT798X)
|
||||
+ if (is_known_accelerated(tfm))
|
||||
siop->flags |= SIOP_FLAG_KERNEL_DRIVER_ONLY;
|
||||
#else
|
||||
- if (is_known_accelerated(tfm))
|
||||
+ if (tfm->__crt_alg->cra_flags & CRYPTO_ALG_KERN_DRIVER_ONLY)
|
||||
siop->flags |= SIOP_FLAG_KERNEL_DRIVER_ONLY;
|
||||
#endif
|
||||
}
|
||||
--- a/main.c
|
||||
+++ b/main.c
|
||||
@@ -168,6 +168,12 @@ __crypto_run_zc(struct csession *ses_ptr
|
||||
struct crypt_op *cop = &kcop->cop;
|
||||
int ret = 0;
|
||||
|
||||
+#if defined(QCANSS)
|
||||
+//openssl bug!!!
|
||||
+ if (unlikely(cop->src != cop->dst)) {
|
||||
+ return __crypto_run_std(ses_ptr, cop);
|
||||
+ }
|
||||
+#endif
|
||||
ret = get_userbuf(ses_ptr, cop->src, cop->len, cop->dst, cop->len,
|
||||
kcop->task, kcop->mm, &src_sg, &dst_sg);
|
||||
if (unlikely(ret)) {
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
net.netfilter.nf_conntrack_acct=1
|
||||
net.netfilter.nf_conntrack_checksum=0
|
||||
net.netfilter.nf_conntrack_max=65535
|
||||
net.netfilter.nf_conntrack_tcp_timeout_established=7440
|
||||
net.netfilter.nf_conntrack_udp_timeout=60
|
||||
net.netfilter.nf_conntrack_udp_timeout_stream=180
|
||||
|
||||
@ -1193,7 +1193,6 @@ endef
|
||||
|
||||
$(eval $(call KernelPackage,crypto-xts))
|
||||
|
||||
|
||||
define KernelPackage/crypto-xxhash
|
||||
TITLE:=xxHash non-cryptographic hash algorithm
|
||||
DEPENDS:=+kmod-crypto-hash +kmod-lib-xxhash
|
||||
@ -1205,3 +1204,20 @@ endef
|
||||
|
||||
$(eval $(call KernelPackage,crypto-xxhash))
|
||||
|
||||
define KernelPackage/crypto-qce
|
||||
TITLE:=QTI Crypto Engine (QCE)
|
||||
KCONFIG:= \
|
||||
CONFIG_CRYPTO_DEV_QCE \
|
||||
CONFIG_CRYPTO_DEV_QCE_AEAD=y \
|
||||
CONFIG_CRYPTO_DEV_QCE_ENABLE_ALL=y \
|
||||
CONFIG_CRYPTO_DEV_QCE_SHA=y \
|
||||
CONFIG_CRYPTO_DEV_QCE_SKCIPHER=y \
|
||||
CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN=512
|
||||
FILES:= \
|
||||
$(LINUX_DIR)/drivers/crypto/qce/qcrypto.ko
|
||||
AUTOLOAD:=$(call AutoLoad,09,qcrypto)
|
||||
DEPENDS:=@TARGET_qualcommax +kmod-crypto-manager +kmod-crypto-hash +kmod-crypto-des
|
||||
$(call AddDepends/crypto)
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,crypto-qce))
|
||||
|
||||
@ -328,6 +328,7 @@ $(eval $(call KernelPackage,ipt-offload))
|
||||
define KernelPackage/ipt-ipopt
|
||||
TITLE:=Modules for matching/changing IP packet options
|
||||
KCONFIG:=$(KCONFIG_IPT_IPOPT)
|
||||
DEPENDS:=+PACKAGE_kmod-nf-conntrack:kmod-nf-conntrack
|
||||
FILES:=$(foreach mod,$(IPT_IPOPT-m),$(LINUX_DIR)/net/$(mod).ko)
|
||||
AUTOLOAD:=$(call AutoProbe,$(notdir $(IPT_IPOPT-m)))
|
||||
$(call AddDepends/ipt)
|
||||
|
||||
@ -36,14 +36,21 @@ PKG_CONFIG_DEPENDS:= \
|
||||
CONFIG_PACKAGE_MAC80211_DEBUGFS \
|
||||
CONFIG_PACKAGE_MAC80211_MESH \
|
||||
CONFIG_PACKAGE_MAC80211_TRACING \
|
||||
CONFIG_PACKAGE_MAC80211_NSS_SUPPORT \
|
||||
CONFIG_PACKAGE_MAC80211_NSS_REDIRECT \
|
||||
CONFIG_PACKAGE_IWLWIFI_DEBUG \
|
||||
CONFIG_PACKAGE_IWLWIFI_DEBUGFS \
|
||||
CONFIG_PACKAGE_RTLWIFI_DEBUG \
|
||||
CONFIG_PACKAGE_RTLWIFI_DEBUG
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
WMENU:=Wireless Drivers
|
||||
|
||||
NSS_PATCH:= subsys ath10k ath11k
|
||||
IPQ_BRANCH:=$(shell git -C $(TOPDIR) rev-parse --abbrev-ref HEAD)
|
||||
IPQ_DATE:=$(shell git -C $(TOPDIR) log -1 --format=%cd --date=format:%Y-%m-%d)
|
||||
IPQ_COMMIT:=$(shell git -C $(TOPDIR) log -1 --format=%h)
|
||||
|
||||
define KernelPackage/mac80211/Default
|
||||
SUBMENU:=$(WMENU)
|
||||
URL:=https://wireless.wiki.kernel.org/
|
||||
@ -129,10 +136,15 @@ define KernelPackage/mac80211
|
||||
$(call KernelPackage/mac80211/Default)
|
||||
TITLE:=Linux 802.11 Wireless Networking Stack
|
||||
# +kmod-crypto-cmac is a runtime only dependency of net/mac80211/aes_cmac.c
|
||||
DEPENDS+= +kmod-cfg80211 +kmod-crypto-cmac +kmod-crypto-ccm +kmod-crypto-gcm +hostapd-common
|
||||
DEPENDS+= +kmod-cfg80211 +kmod-crypto-cmac +kmod-crypto-ccm +kmod-crypto-gcm +hostapd-common \
|
||||
+ATH11K_NSS_SUPPORT:kmod-qca-nss-drv
|
||||
KCONFIG:=\
|
||||
CONFIG_AVERAGE=y
|
||||
FILES:= $(PKG_BUILD_DIR)/net/mac80211/mac80211.ko
|
||||
ifdef CONFIG_PACKAGE_MAC80211_NSS_REDIRECT
|
||||
AUTOLOAD:=$(call AutoProbe, mac80211)
|
||||
MODPARAMS.mac80211:=nss_redirect=1
|
||||
endif
|
||||
ABI_VERSION:=$(PKG_VERSION)-$(PKG_RELEASE)
|
||||
MENU:=1
|
||||
endef
|
||||
@ -140,6 +152,21 @@ endef
|
||||
define KernelPackage/mac80211/config
|
||||
if PACKAGE_kmod-mac80211
|
||||
|
||||
if PACKAGE_kmod-qca-nss-drv
|
||||
config PACKAGE_MAC80211_NSS_SUPPORT
|
||||
bool "Enable NSS support"
|
||||
default y
|
||||
help
|
||||
This option enables support for NSS in QCA boards.
|
||||
config PACKAGE_MAC80211_NSS_REDIRECT
|
||||
bool "Enable autoloading with 'nss_redirect=1' (not needed on ath11k)"
|
||||
depends on PACKAGE_MAC80211_NSS_SUPPORT
|
||||
default n
|
||||
help
|
||||
This option enables autoloading mac80211 with 'nss_redirect=1'.
|
||||
However, it is not required for wifi offloading.
|
||||
endif
|
||||
|
||||
config PACKAGE_MAC80211_DEBUGFS
|
||||
bool "Export mac80211 internals in DebugFS"
|
||||
select KERNEL_DEBUG_FS
|
||||
@ -281,6 +308,16 @@ ifeq ($(BUILD_VARIANT),smallbuffers)
|
||||
C_DEFINES+= -DCONFIG_ATH10K_SMALLBUFFERS
|
||||
endif
|
||||
|
||||
ifdef CONFIG_ATH11K_NSS_SUPPORT
|
||||
IREMAP_CFLAGS+=-I$(STAGING_DIR)/usr/include/qca-nss-drv -I$(STAGING_DIR)/usr/include/qca-nss-clients
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSS_FIRMWARE_VERSION_11_4),y)
|
||||
C_DEFINES+=-DCONFIG_NSS_FIRMWARE_VERSION_11_4
|
||||
endif
|
||||
|
||||
config-$(CONFIG_PACKAGE_MAC80211_NSS_SUPPORT) += MAC80211_NSS_SUPPORT
|
||||
|
||||
MAKE_OPTS:= \
|
||||
$(subst -C $(LINUX_DIR),-C "$(PKG_BUILD_DIR)",$(KERNEL_MAKEOPTS)) \
|
||||
EXTRA_CFLAGS="-I$(PKG_BUILD_DIR)/include $(IREMAP_CFLAGS) $(C_DEFINES)" \
|
||||
@ -354,6 +391,11 @@ define Build/Patch
|
||||
$(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/mwl,mwl/)
|
||||
$(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/brcm,brcm/)
|
||||
$(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/rtl,rtl/)
|
||||
ifdef CONFIG_ATH11K_NSS_SUPPORT
|
||||
$(foreach driver,$(NSS_PATCH),
|
||||
$(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/nss/$(driver),nss/$(driver)/)
|
||||
)
|
||||
endif
|
||||
$(if $(QUILT),touch $(PKG_BUILD_DIR)/.quilt_used)
|
||||
endef
|
||||
|
||||
@ -371,6 +413,11 @@ define Quilt/Refresh/Package
|
||||
$(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/mwl,mwl/)
|
||||
$(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/brcm,brcm/)
|
||||
$(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/rtl,rtl/)
|
||||
ifdef CONFIG_ATH11K_NSS_SUPPORT
|
||||
$(foreach driver,$(NSS_PATCH),
|
||||
$(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/nss/$(driver),nss/$(driver)/)
|
||||
)
|
||||
endif
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
@ -392,6 +439,18 @@ define Build/InstallDev
|
||||
rm -f $(1)/usr/include/mac80211-backport/linux/module.h
|
||||
endef
|
||||
|
||||
ifdef CONFIG_ATH11K_NSS_SUPPORT
|
||||
define KernelPackage/ath11k/install
|
||||
$(INSTALL_DIR) $(1)/etc/init.d $(1)/etc/config $(1)/usr/bin $(1)/etc/hotplug.d/net
|
||||
$(INSTALL_BIN) ./files/qca-nss-pbuf.init $(1)/etc/init.d/qca-nss-pbuf
|
||||
$(INSTALL_DATA) ./files/pbuf.uci $(1)/etc/config/pbuf
|
||||
$(INSTALL_BIN) ./files/nss_diag.sh $(1)/usr/bin/nss_diag
|
||||
$(INSTALL_DATA) ./files/disable_mesh_chksum_ath11k.hotplug $(1)/etc/hotplug.d/net/99-disable_mesh_chksum_ath11k
|
||||
echo "IPQ_BRANCH=$(IPQ_BRANCH)" > $(1)/etc/ipq_release
|
||||
echo "IPQ_DATE=$(IPQ_DATE)" >> $(1)/etc/ipq_release
|
||||
echo "IPQ_COMMIT=$(IPQ_COMMIT)" >> $(1)/etc/ipq_release
|
||||
endef
|
||||
endif
|
||||
|
||||
$(eval $(foreach drv,$(PKG_DRIVERS),$(call KernelPackage,$(drv))))
|
||||
$(eval $(call KernelPackage,cfg80211))
|
||||
|
||||
@ -13,7 +13,14 @@ PKG_CONFIG_DEPENDS += \
|
||||
CONFIG_ATH10K_LEDS \
|
||||
CONFIG_ATH10K_THERMAL \
|
||||
CONFIG_ATH11K_THERMAL \
|
||||
CONFIG_ATH_USER_REGD
|
||||
CONFIG_ATH11K_DEBUGFS_STA \
|
||||
CONFIG_ATH11K_DEBUGFS_HTT_STATS \
|
||||
CONFIG_ATH_USER_REGD \
|
||||
CONFIG_ATH11K_MEM_PROFILE_1G \
|
||||
CONFIG_ATH11K_MEM_PROFILE_512M \
|
||||
CONFIG_ATH11K_MEM_PROFILE_256M \
|
||||
CONFIG_ATH11K_NSS_SUPPORT \
|
||||
CONFIG_ATH11K_NSS_MESH_SUPPORT
|
||||
|
||||
ifdef CONFIG_PACKAGE_MAC80211_DEBUGFS
|
||||
config-y += \
|
||||
@ -59,6 +66,13 @@ config-$(CONFIG_ATH9K_UBNTHSR) += ATH9K_UBNTHSR
|
||||
config-$(CONFIG_ATH10K_LEDS) += ATH10K_LEDS
|
||||
config-$(CONFIG_ATH10K_THERMAL) += ATH10K_THERMAL
|
||||
config-$(CONFIG_ATH11K_THERMAL) += ATH11K_THERMAL
|
||||
config-$(CONFIG_ATH11K_MEM_PROFILE_1G) += ATH11K_MEM_PROFILE_1G
|
||||
config-$(CONFIG_ATH11K_MEM_PROFILE_512M) += ATH11K_MEM_PROFILE_512M
|
||||
config-$(CONFIG_ATH11K_MEM_PROFILE_256M) += ATH11K_MEM_PROFILE_256M
|
||||
config-$(CONFIG_ATH11K_NSS_SUPPORT) += ATH11K_NSS_SUPPORT
|
||||
config-$(CONFIG_ATH11K_NSS_MESH_SUPPORT) += ATH11K_NSS_MESH_SUPPORT
|
||||
config-$(CONFIG_ATH11K_DEBUGFS_STA) += ATH11K_DEBUGFS_STA
|
||||
config-$(CONFIG_ATH11K_DEBUGFS_HTT_STATS) += ATH11K_DEBUGFS_HTT_STATS
|
||||
|
||||
config-$(call config_package,ath9k-htc) += ATH9K_HTC
|
||||
config-$(call config_package,ath10k,regular) += ATH10K ATH10K_PCI
|
||||
@ -331,8 +345,16 @@ define KernelPackage/ath11k
|
||||
URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath11k
|
||||
DEPENDS+= +kmod-ath +@DRIVER_11AC_SUPPORT +@DRIVER_11AX_SUPPORT \
|
||||
+kmod-crypto-michael-mic +ATH11K_THERMAL:kmod-hwmon-core \
|
||||
+ATH11K_THERMAL:kmod-thermal +kmod-qcom-qmi-helpers
|
||||
+ATH11K_THERMAL:kmod-thermal +kmod-qcom-qmi-helpers \
|
||||
+ATH11K_NSS_SUPPORT:kmod-qca-nss-drv \
|
||||
+ATH11K_NSS_MESH_SUPPORT:kmod-qca-nss-drv-wifi-meshmgr \
|
||||
+@(ATH11K_NSS_SUPPORT):NSS_DRV_WIFIOFFLOAD_ENABLE \
|
||||
+@(ATH11K_NSS_SUPPORT):NSS_DRV_WIFI_EXT_VDEV_ENABLE
|
||||
FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath11k/ath11k.ko
|
||||
ifdef CONFIG_ATH11K_NSS_SUPPORT
|
||||
AUTOLOAD:=$(call AutoProbe,ath11k)
|
||||
MODPARAMS.ath11k:=nss_offload=1 frame_mode=2
|
||||
endif
|
||||
endef
|
||||
|
||||
define KernelPackage/ath11k/description
|
||||
@ -340,6 +362,10 @@ This module adds support for Qualcomm Technologies 802.11ax family of
|
||||
chipsets.
|
||||
endef
|
||||
|
||||
define KernelPackage/ath11k/conffiles
|
||||
/etc/config/pbuf
|
||||
endef
|
||||
|
||||
define KernelPackage/ath11k/config
|
||||
|
||||
config ATH11K_THERMAL
|
||||
@ -347,6 +373,63 @@ define KernelPackage/ath11k/config
|
||||
depends on PACKAGE_kmod-ath11k
|
||||
default y if TARGET_qualcommax
|
||||
|
||||
config ATH11K_DEBUGFS_STA
|
||||
bool "Enable ath11k station statistics"
|
||||
depends on PACKAGE_kmod-ath11k
|
||||
depends on PACKAGE_MAC80211_DEBUGFS
|
||||
default y
|
||||
help
|
||||
Say Y to enable access to the station statistics via debugfs.
|
||||
|
||||
config ATH11K_DEBUGFS_HTT_STATS
|
||||
bool "Enable ath11k HTT statistics"
|
||||
depends on PACKAGE_kmod-ath11k
|
||||
depends on PACKAGE_MAC80211_DEBUGFS
|
||||
default y
|
||||
help
|
||||
Say Y to enable access to the HTT statistics via debugfs.
|
||||
|
||||
config ATH11K_NSS_SUPPORT
|
||||
bool "Enable NSS WiFi offload"
|
||||
select ATH11K_MEM_PROFILE_512M
|
||||
select PACKAGE_kmod-qca-nss-ecm
|
||||
default y
|
||||
help
|
||||
Say Y to enable NSS WiFi offload support. Ensure you enable feeds for NSS drivers.
|
||||
https://github.com/qosmio/nss-packages
|
||||
|
||||
config ATH11K_NSS_MESH_SUPPORT
|
||||
bool "Enable NSS WiFi Mesh offload"
|
||||
depends on ATH11K_NSS_SUPPORT
|
||||
select PACKAGE_MAC80211_MESH
|
||||
select NSS_FIRMWARE_VERSION_11_4
|
||||
default n
|
||||
|
||||
choice
|
||||
prompt "Memory Profile"
|
||||
depends on PACKAGE_kmod-ath11k
|
||||
default ATH11K_MEM_PROFILE_512M
|
||||
help
|
||||
This option allows you to select the memory profile.
|
||||
It should correspond to the total RAM of your board.
|
||||
|
||||
config ATH11K_MEM_PROFILE_1G
|
||||
bool "Use 1G memory profile"
|
||||
help
|
||||
This allows configuring ath11k for boards with 1GB+ memory.
|
||||
|
||||
config ATH11K_MEM_PROFILE_512M
|
||||
bool "Use 512MB memory profile"
|
||||
help
|
||||
This allows configuring ath11k for boards with 512M memory.
|
||||
The default is 1GB if not selected
|
||||
|
||||
config ATH11K_MEM_PROFILE_256M
|
||||
bool "Use 256MB memory profile"
|
||||
help
|
||||
This allows configuring ath11k for boards with 256M memory.
|
||||
The default is 1GB if not selected
|
||||
endchoice
|
||||
endef
|
||||
|
||||
define KernelPackage/ath11k-ahb
|
||||
|
||||
24
package/kernel/mac80211/files/disable_mesh_chksum_ath11k.hotplug
Executable file
24
package/kernel/mac80211/files/disable_mesh_chksum_ath11k.hotplug
Executable file
@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
# shellcheck disable=1090
|
||||
PROG=${0##*/}
|
||||
[ "$ACTION" = "add" ] && [ "$DEVTYPE" = "wlan" ] || exit 0
|
||||
|
||||
UEVENT="/sys/class/net/$INTERFACE/device/uevent"
|
||||
[ -r "$UEVENT" ] || exit 0
|
||||
|
||||
DRIVER=$(awk -F= '/^DRIVER/{print $2}' "$UEVENT")
|
||||
case "$DRIVER" in
|
||||
*ath11k*)
|
||||
mode=$(ubus call network.wireless status \
|
||||
| jsonfilter -e "@[*].interfaces[@.ifname='$INTERFACE'].config.mode" 2> /dev/null)
|
||||
[ "$mode" = "mesh" ] || exit 0
|
||||
|
||||
INC="/lib/netifd/offload/disable_offloads.sh"
|
||||
. "$INC" 2> /dev/null || {
|
||||
logger -t "$PROG" -p user.error "missing include script $INC. exiting..."
|
||||
exit 1
|
||||
}
|
||||
|
||||
disable_feature tx-checksumming "$INTERFACE"
|
||||
;;
|
||||
esac
|
||||
84
package/kernel/mac80211/files/nss_diag.sh
Executable file
84
package/kernel/mac80211/files/nss_diag.sh
Executable file
@ -0,0 +1,84 @@
|
||||
#!/bin/sh
|
||||
# shellcheck disable=3037,3060,2034,1091,2166
|
||||
|
||||
# check if stdout is a terminal, then set colors.
|
||||
if [ -t 1 ]; then
|
||||
red="\033[31m"
|
||||
green="\033[32m"
|
||||
yellow="\033[33m"
|
||||
blue="\033[34m"
|
||||
magenta="\033[35m"
|
||||
cyan="\033[36m"
|
||||
white="\033[37m"
|
||||
reset="\033[m"
|
||||
bold="\033[1m"
|
||||
fi
|
||||
|
||||
# Retrieve OpenWRT version
|
||||
[ -r /etc/openwrt_version ] && openwrt_rev=$(cat /etc/openwrt_version)
|
||||
|
||||
# Retrieve device model
|
||||
model=$(jsonfilter -e ''@.model.name'' < /etc/board.json | sed -e "s/,/_/g")
|
||||
|
||||
# NSS firmware version
|
||||
nss_fw="/lib/firmware/qca*.bin"
|
||||
# shellcheck disable=2086
|
||||
[ "$(ls $nss_fw 2> /dev/null)" ] && nss_version=$(grep -h -m 1 -a -o 'Version:.[^[:cntrl:]]*' $nss_fw | head -1 | cut -d ' ' -f 2)
|
||||
|
||||
# ATH11K firmware version
|
||||
ath11k_fw=$(grep -hm1 -a -o 'WLAN.[^[:cntrl:]]*SILICONZ-1' /lib/firmware/*/q6* | head -1)
|
||||
|
||||
# MAC80211 (backports) version
|
||||
mac80211_version=$(awk '/version/{print $NF;exit}' /lib/modules/*/compat.ko)
|
||||
|
||||
# OpenWRT IPQ release details
|
||||
[ -r /etc/ipq_release ] && . /etc/ipq_release
|
||||
ipq_branch=${IPQ_BRANCH:-"N/A"}
|
||||
ipq_commit=${IPQ_COMMIT:-"N/A"}
|
||||
ipq_date=${IPQ_DATE:-"N/A"}
|
||||
|
||||
# Defaults for empty variables
|
||||
openwrt_rev=${openwrt_rev:-"N/A"}
|
||||
model=${model:-"N/A"}
|
||||
nss_version=${nss_version:-"N/A"}
|
||||
ath11k_fw=${ath11k_fw:-"N/A"}
|
||||
mac80211_version=${mac80211_version:-"N/A"}
|
||||
|
||||
# Display the information
|
||||
echo -e "${bold}${red} MODEL${reset}: ${blue}${bold}${model}${reset}"
|
||||
echo -e "${bold}${red} OPENWRT${reset}: ${white}${openwrt_rev}${reset}"
|
||||
echo -e "${bold}${red}IPQ BRANCH${reset}: ${cyan}${ipq_branch}${reset}"
|
||||
echo -e "${bold}${red}IPQ COMMIT${reset}: ${cyan}${ipq_commit}${reset}"
|
||||
echo -e "${bold}${red} IPQ DATE${reset}: ${cyan}${ipq_date}${reset}"
|
||||
echo -e "${bold}${red} NSS FW${reset}: ${magenta}${nss_version}${reset}"
|
||||
echo -e "${bold}${red} MAC80211${reset}: ${yellow}${mac80211_version}${reset}"
|
||||
echo -e "${bold}${red} ATH11K FW${reset}: ${green}${ath11k_fw}${reset}"
|
||||
|
||||
# Display GRO Fragmentation status using BusyBox
|
||||
echo -ne "${bold}${red} INTERFACE${reset}: ${white}"
|
||||
n=0
|
||||
for iface in /sys/class/net/br-lan/device /sys/class/net/*/device; do
|
||||
iface=${iface%/*}
|
||||
iface=${iface##*/}
|
||||
ethtool -k "$iface" | awk -v n=$n -v i="$iface" -v rst="${reset}" -v red="${red}" -v green="${green}" '
|
||||
BEGIN { settings=""; if(n>0) spacing=" " }
|
||||
/tx-checksumming|rx-gro-list/ {
|
||||
color=green
|
||||
if($2=="off") color=red
|
||||
settings = settings $1 " " sprintf("%s%-3s%s", color,$2,rst) " ";
|
||||
}
|
||||
END { printf "%s%-11s%s\n", spacing, i, settings; }'
|
||||
n=$((n + 1))
|
||||
done
|
||||
|
||||
echo -e "${reset}"
|
||||
echo -ne "${bold}${red} NSS PKGS${reset}: ${white}"
|
||||
|
||||
apk list -I | awk -v count=0 '
|
||||
/kmod-qca|^nss/ {
|
||||
if(count>0) tab=" "
|
||||
print tab $1
|
||||
count++
|
||||
}'
|
||||
|
||||
echo -ne "${reset}"
|
||||
8
package/kernel/mac80211/files/pbuf.uci
Executable file
8
package/kernel/mac80211/files/pbuf.uci
Executable file
@ -0,0 +1,8 @@
|
||||
config general opt
|
||||
option auto_scale 'off'
|
||||
# option memory_profile 'off'
|
||||
option memory_profile 'auto'
|
||||
# option memory_profile '1gb'
|
||||
# option memory_profile '512mb'
|
||||
# option memory_profile '256mb'
|
||||
option scaling_governor 'schedutil'
|
||||
182
package/kernel/mac80211/files/qca-nss-pbuf.init
Executable file
182
package/kernel/mac80211/files/qca-nss-pbuf.init
Executable file
@ -0,0 +1,182 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# shellcheck disable=3043,3010
|
||||
# Copyright (c) 2021 The Linux Foundation. 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.
|
||||
#
|
||||
|
||||
START=95
|
||||
NAME=qca-nss-pbuf
|
||||
|
||||
reload_wifi() {
|
||||
if [ -r /sys/module/ath11k/parameters/nss_offload ]; then
|
||||
nss_offload=$(cat /sys/module/ath11k/parameters/nss_offload 2> /dev/null)
|
||||
[ "$nss_offload" -eq 1 ] && wifi up
|
||||
fi
|
||||
}
|
||||
|
||||
get_num_cpus() {
|
||||
local num_cpus
|
||||
num_cpus=$(awk -F': ' '/^processor/ {count++} END {print count}' /proc/cpuinfo)
|
||||
echo "${num_cpus:-1}"
|
||||
}
|
||||
|
||||
apply_sysctl() {
|
||||
[ "$(sysctl -n -e dev.nss.general.redirect)" -eq 0 ] && /etc/init.d/qca-nss-ecm start
|
||||
|
||||
# Running this script multiple times is useless, as extra_pbuf_core0
|
||||
# can't be changed if it is allocated, assume it's already been run.
|
||||
if [ "$(sysctl -n -e dev.nss.n2hcfg.extra_pbuf_core0)" -eq 0 ]; then
|
||||
logger -t $NAME "$board - setting dev.nss.n2hcfg.extra_pbuf_core0=$extra_pbuf_core0"
|
||||
sysctl -w dev.nss.n2hcfg.extra_pbuf_core0="$extra_pbuf_core0" > /dev/null 2>&1
|
||||
else
|
||||
logger -t $NAME "Sysctl key 'extra_pbuf_core0' already set to '""$extra_pbuf_core0""'. Skipping applying wifi nss configs"
|
||||
fi
|
||||
|
||||
sysctl -w dev.nss.n2hcfg.n2h_high_water_core0="$n2h_high_water_core0" > /dev/null 2>&1
|
||||
|
||||
logger -t $NAME "$board - setting dev.nss.n2hcfg.n2h_wifi_pool_buf=$n2h_wifi_pool_buf"
|
||||
sysctl -w dev.nss.n2hcfg.n2h_wifi_pool_buf="$n2h_wifi_pool_buf" > /dev/null 2>&1
|
||||
|
||||
logger -t $NAME "$board - setting dev.nss.n2hcfg.n2h_high_water_core0=$n2h_high_water_core0"
|
||||
sysctl -w dev.nss.n2hcfg.n2h_high_water_core0="$n2h_high_water_core0" > /dev/null 2>&1
|
||||
|
||||
}
|
||||
|
||||
apply_nss_config() {
|
||||
local auto_scale n2h_queue_limit_core0 n2h_queue_limit_core1 num_cpus
|
||||
local hash_bitmap
|
||||
|
||||
if [ ! -r /sys/module/ath11k/parameters/nss_offload ]; then
|
||||
logger -t $NAME "Module parameter '/sys/module/ath11k/parameters/nss_offload' does NOT exist. Skipping applying wifi nss configs"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
enable_nss_offload=$(cat /sys/module/ath11k/parameters/nss_offload)
|
||||
|
||||
if [ "$enable_nss_offload" -ne "1" ]; then
|
||||
logger -t $NAME -s user.warn "Module parameter 'nss_offload=0'. Skipping applying wifi nss configs"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
[ ! -d "/proc/sys/dev/nss/rps" ] && {
|
||||
logger -s -t $NAME -p user.error "NSS driver not loaded or disabled! Exiting... "
|
||||
exit 1
|
||||
}
|
||||
|
||||
config_load pbuf
|
||||
config_get_bool auto_scale opt auto_scale 0
|
||||
config_get n2h_queue_limit_core0 opt n2h_queue_limit_core0 256
|
||||
config_get n2h_queue_limit_core1 opt n2h_queue_limit_core1 256
|
||||
|
||||
sysctl -w dev.nss.clock.auto_scale="$auto_scale" > /dev/null 2>&1
|
||||
|
||||
sysctl -w dev.nss.n2hcfg.n2h_queue_limit_core0="$n2h_queue_limit_core0" > /dev/null 2>&1
|
||||
sysctl -w dev.nss.n2hcfg.n2h_queue_limit_core1="$n2h_queue_limit_core1" > /dev/null 2>&1
|
||||
|
||||
local memory_profile memtotal board
|
||||
board=$(board_name)
|
||||
|
||||
if memory_profile=$(uci_get pbuf.opt.memory_profile); then
|
||||
case "$memory_profile" in
|
||||
1024 | 1g* | 512 | 512m* | 256 | 256m*)
|
||||
logger -t $NAME "Using custom memory profile - $board"
|
||||
;;
|
||||
off* | false* | disable* | 0)
|
||||
logger -s -t $NAME -p user.warn "NSS pbuf option 'memory_profile=off'. Not running. Enable if you have issues connecting more than 65 clients"
|
||||
exit 0
|
||||
;;
|
||||
auto)
|
||||
memtotal=$(awk '/MemTotal/{print $2}' /proc/meminfo)
|
||||
[ "$memtotal" -gt 512000 ] && memory_profile=1024
|
||||
[ "$memtotal" -le 512000 ] && memory_profile=512
|
||||
[ "$memtotal" -le 256000 ] && memory_profile=256
|
||||
logger -t $NAME "Setting n2hcfg values for board: $board"
|
||||
;;
|
||||
*)
|
||||
logger -s -t $NAME -p user.error "Unknown profile $memory_profile. Choose auto, 1gb, 512mb, or 256mb"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
|
||||
case "$memory_profile" in
|
||||
# 1GB+ profile
|
||||
1024 | 1g*)
|
||||
extra_pbuf_core0=10000000 n2h_high_water_core0=72512 n2h_wifi_pool_buf=36864 apply_sysctl
|
||||
;;
|
||||
# 512MB profile
|
||||
512 | 512m*)
|
||||
extra_pbuf_core0=3100000 n2h_high_water_core0=30624 n2h_wifi_pool_buf=8192 apply_sysctl
|
||||
;;
|
||||
# 256MB profile
|
||||
256 | 256m*)
|
||||
extra_pbuf_core0=3100000 n2h_high_water_core0=30258 n2h_wifi_pool_buf=4096 apply_sysctl
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
set_stats_disable() {
|
||||
|
||||
local stats_disable
|
||||
config_load pbuf
|
||||
config_get stats_disable opt stats_disable 1
|
||||
|
||||
find /sys/kernel/debug/ath11k -name stats_disable | while read -r stats_file; do
|
||||
stats_msg_prefix="Disabling"
|
||||
[ "$stats_disable" -eq 0 ] && stats_msg_prefix="Enabling"
|
||||
logger -t $NAME -p user.notice "$stats_msg_prefix ath11k stats"
|
||||
echo "$stats_disable" > "$stats_file"
|
||||
done
|
||||
}
|
||||
|
||||
set_scaling_governor() {
|
||||
|
||||
local scaling_governor num_cpus
|
||||
config_load pbuf
|
||||
config_get scaling_governor opt scaling_governor
|
||||
|
||||
scaling_available_governors=/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
|
||||
|
||||
if [ -r "$scaling_available_governors" ]; then
|
||||
scaling_available_governors=$(cat $scaling_available_governors)
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ -n "$scaling_available_governors" ] && [ -n "$scaling_governor" ]; then
|
||||
if [[ "$scaling_available_governors" =~ $scaling_governor ]]; then
|
||||
logger -t $NAME -p user.notice "Setting CPU scaling governor to '$scaling_governor'"
|
||||
num_cpus=$(get_num_cpus)
|
||||
for num in $(seq 0 $((num_cpus - 1))); do
|
||||
echo "$scaling_governor" > "/sys/devices/system/cpu/cpu${num}/cpufreq/scaling_governor"
|
||||
done
|
||||
else
|
||||
logger -t $NAME -p user.error "'$scaling_governor' not available in CPU governors [ $scaling_available_governors ]"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
start() {
|
||||
|
||||
set_scaling_governor
|
||||
set_stats_disable
|
||||
apply_nss_config
|
||||
|
||||
num_cpus=$(get_num_cpus)
|
||||
hash_bitmap="$(((1 << num_cpus) - 1))"
|
||||
sysctl -w dev.nss.rps.hash_bitmap=$hash_bitmap > /dev/null 2>&1
|
||||
reload_wifi
|
||||
|
||||
}
|
||||
@ -41,7 +41,7 @@ Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
}
|
||||
} else {
|
||||
ab->qmi.target_mem[idx].paddr = 0;
|
||||
@@ -2292,6 +2296,7 @@ static int ath11k_qmi_load_file_target_m
|
||||
@@ -2295,6 +2299,7 @@ static int ath11k_qmi_load_file_target_m
|
||||
struct qmi_wlanfw_bdf_download_resp_msg_v01 resp;
|
||||
struct qmi_txn txn;
|
||||
const u8 *temp = data;
|
||||
@ -49,7 +49,7 @@ Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
||||
void __iomem *bdf_addr = NULL;
|
||||
int ret = 0;
|
||||
u32 remaining = len;
|
||||
@@ -2303,7 +2308,9 @@ static int ath11k_qmi_load_file_target_m
|
||||
@@ -2306,7 +2311,9 @@ static int ath11k_qmi_load_file_target_m
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
|
||||
if (ab->hw_params.fixed_bdf_addr) {
|
||||
|
||||
@ -91,9 +91,9 @@ Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
#endif /* _HIF_H_ */
|
||||
--- a/drivers/net/wireless/ath/ath11k/qmi.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
|
||||
@@ -2184,6 +2184,8 @@ static int ath11k_qmi_request_device_inf
|
||||
ab->mem = bar_addr_va;
|
||||
ab->mem_len = resp.bar_size;
|
||||
@@ -2187,6 +2187,8 @@ static int ath11k_qmi_request_device_inf
|
||||
if (!ab->hw_params.ce_remap)
|
||||
ab->mem_ce = ab->mem;
|
||||
|
||||
+ ath11k_hif_config_static_window(ab);
|
||||
+
|
||||
|
||||
@ -89,7 +89,7 @@ Signed-off-by: George Moussalem <george.moussalem@outlook.com>
|
||||
/* SMBIOS type containing Board Data File Name Extension */
|
||||
#define ATH11K_SMBIOS_BDF_EXT_TYPE 0xF8
|
||||
|
||||
@@ -945,6 +948,7 @@ struct ath11k_base {
|
||||
@@ -951,6 +954,7 @@ struct ath11k_base {
|
||||
struct list_head peers;
|
||||
wait_queue_head_t peer_mapping_wq;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
|
||||
@ -132,7 +132,7 @@ Signed-off-by: Sriram R <srirrama@codeaurora.org>
|
||||
};
|
||||
|
||||
/* HTT definitions */
|
||||
@@ -1712,5 +1718,6 @@ void ath11k_dp_shadow_init_timer(struct
|
||||
@@ -1689,5 +1695,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);
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
Remove not needed warning when get peer unmap
|
||||
event from the firmware. This is not critical
|
||||
message. Instead print this as a debug message.
|
||||
|
||||
Signed-off-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
|
||||
---
|
||||
drivers/net/wireless/ath/ath10k/txrx.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath10k/txrx.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
|
||||
@@ -266,7 +266,7 @@ void ath10k_peer_unmap_event(struct ath1
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
peer = ath10k_peer_find_by_id(ar, ev->peer_id);
|
||||
if (!peer) {
|
||||
- ath10k_warn(ar, "peer-unmap-event: unknown peer id %d\n",
|
||||
+ ath10k_dbg(ar, ATH10K_DBG_HTT, "peer-unmap-event: unknown peer id %d\n",
|
||||
ev->peer_id);
|
||||
goto exit;
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
--- a/drivers/net/wireless/ath/ath10k/pci.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/pci.c
|
||||
@@ -1975,6 +1975,7 @@ static int ath10k_pci_hif_start(struct a
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif start\n");
|
||||
|
||||
+ dev_set_threaded(ar->napi_dev, true);
|
||||
ath10k_core_napi_enable(ar);
|
||||
|
||||
ath10k_pci_irq_enable(ar);
|
||||
--- a/drivers/net/wireless/ath/ath10k/sdio.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
|
||||
@@ -1863,6 +1863,7 @@ static int ath10k_sdio_hif_start(struct
|
||||
struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
|
||||
int ret;
|
||||
|
||||
+ dev_set_threaded(&ar->napi_dev, true);
|
||||
ath10k_core_napi_enable(ar);
|
||||
|
||||
/* Sleep 20 ms before HIF interrupts are disabled.
|
||||
--- a/drivers/net/wireless/ath/ath10k/core.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/core.c
|
||||
@@ -3708,6 +3708,10 @@ struct ath10k *ath10k_core_create(size_t
|
||||
if (!ar->napi_dev)
|
||||
goto err_free_tx_complete;
|
||||
|
||||
+ snprintf(ar->napi_dev->name, sizeof(ar->napi_dev->name), "ath10k_%s",
|
||||
+ wiphy_name(ar->hw->wiphy));
|
||||
+ dev_set_threaded(ar->napi_dev, true);
|
||||
+
|
||||
ret = ath10k_coredump_create(ar);
|
||||
if (ret)
|
||||
goto err_free_netdev;
|
||||
--- a/drivers/net/wireless/ath/ath10k/ahb.c
|
||||
+++ b/drivers/net/wireless/ath/ath10k/ahb.c
|
||||
@@ -622,6 +622,7 @@ static int ath10k_ahb_hif_start(struct a
|
||||
ath10k_core_napi_enable(ar);
|
||||
ath10k_ce_enable_interrupts(ar);
|
||||
ath10k_pci_enable_intx_irq(ar);
|
||||
+ dev_set_threaded(&ar->napi_dev, true);
|
||||
|
||||
ath10k_pci_rx_post(ar);
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
||||
@@ -4275,22 +4275,28 @@ static int ath11k_clear_peer_keys(struct
|
||||
int ret;
|
||||
int i;
|
||||
u32 flags = 0;
|
||||
+ struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
peer = ath11k_peer_find(ab, arvif->vdev_id, addr);
|
||||
- spin_unlock_bh(&ab->base_lock);
|
||||
-
|
||||
- if (!peer)
|
||||
+ if (!peer) {
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
return -ENOENT;
|
||||
+ }
|
||||
+ for (i = 0; i < ARRAY_SIZE(keys); i++) {
|
||||
+ keys[i]= peer->keys[i];
|
||||
+ peer->keys[i]= NULL;
|
||||
+ }
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {
|
||||
- if (!peer->keys[i])
|
||||
+ for (i = 0; i < ARRAY_SIZE(keys); i++) {
|
||||
+ if (!keys[i])
|
||||
continue;
|
||||
|
||||
/* key flags are not required to delete the key */
|
||||
- ret = ath11k_install_key(arvif, peer->keys[i],
|
||||
+ ret = ath11k_install_key(arvif, keys[i],
|
||||
DISABLE_KEY, addr, flags);
|
||||
if (ret < 0 && first_errno == 0)
|
||||
first_errno = ret;
|
||||
@@ -4298,10 +4304,6 @@ static int ath11k_clear_peer_keys(struct
|
||||
if (ret < 0)
|
||||
ath11k_warn(ab, "failed to remove peer key %d: %d\n",
|
||||
i, ret);
|
||||
-
|
||||
- spin_lock_bh(&ab->base_lock);
|
||||
- peer->keys[i] = NULL;
|
||||
- spin_unlock_bh(&ab->base_lock);
|
||||
}
|
||||
|
||||
return first_errno;
|
||||
@ -0,0 +1,671 @@
|
||||
From 4635ca1f29bc5838d556b09e3c186b76a5198ddb Mon Sep 17 00:00:00 2001
|
||||
From: Manikanta Pubbisetty <mpubbise@codeaurora.org>
|
||||
Date: Fri, 18 Aug 2023 11:43:33 +0530
|
||||
Subject: [PATCH] ath11k: add rx histogram stats
|
||||
|
||||
Adding rx rate table and byte level peer rx statistics. Also,
|
||||
adding a debugfs knob to reset rx stats specific to the peer.
|
||||
|
||||
Signed-off-by: Manikanta Pubbisetty <mpubbise@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/core.h | 19 ++-
|
||||
drivers/net/wireless/ath/ath11k/debugfs_sta.c | 152 ++++++++++++++++--
|
||||
drivers/net/wireless/ath/ath11k/dp_rx.c | 95 +++++++++--
|
||||
drivers/net/wireless/ath/ath11k/dp_rx.h | 19 +++
|
||||
drivers/net/wireless/ath/ath11k/hal_rx.c | 85 +++++++---
|
||||
drivers/net/wireless/ath/ath11k/hal_rx.h | 21 +++
|
||||
drivers/net/wireless/ath/ath11k/hw.c | 18 +++
|
||||
drivers/net/wireless/ath/ath11k/hw.h | 1 +
|
||||
8 files changed, 351 insertions(+), 59 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/core.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
||||
@@ -44,6 +44,8 @@
|
||||
|
||||
#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
|
||||
|
||||
#define ATH11K_QCN6122_USERPD_2 1
|
||||
#define ATH11K_QCN6122_USERPD_3 2
|
||||
@@ -429,6 +431,17 @@ struct ath11k_vif_iter {
|
||||
struct ath11k_vif *arvif;
|
||||
};
|
||||
|
||||
+struct ath11k_rx_peer_rate_stats {
|
||||
+ u64 ht_mcs_count[HAL_RX_MAX_MCS_HT + 1];
|
||||
+ u64 vht_mcs_count[HAL_RX_MAX_MCS_VHT + 1];
|
||||
+ u64 he_mcs_count[HAL_RX_MAX_MCS_HE + 1];
|
||||
+ u64 nss_count[HAL_RX_MAX_NSS];
|
||||
+ u64 bw_count[HAL_RX_BW_MAX];
|
||||
+ u64 gi_count[HAL_RX_GI_MAX];
|
||||
+ u64 legacy_count[HAL_RX_MAX_NUM_LEGACY_RATES];
|
||||
+ u64 rx_rate[ATH11K_RX_RATE_TABLE_11AX_NUM];
|
||||
+};
|
||||
+
|
||||
struct ath11k_rx_peer_stats {
|
||||
u64 num_msdu;
|
||||
u64 num_mpdu_fcs_ok;
|
||||
@@ -440,10 +453,6 @@ struct ath11k_rx_peer_stats {
|
||||
u64 non_ampdu_msdu_count;
|
||||
u64 stbc_count;
|
||||
u64 beamformed_count;
|
||||
- u64 mcs_count[HAL_RX_MAX_MCS + 1];
|
||||
- u64 nss_count[HAL_RX_MAX_NSS];
|
||||
- u64 bw_count[HAL_RX_BW_MAX];
|
||||
- u64 gi_count[HAL_RX_GI_MAX];
|
||||
u64 coding_count[HAL_RX_SU_MU_CODING_MAX];
|
||||
u64 tid_count[IEEE80211_NUM_TIDS + 1];
|
||||
u64 pream_cnt[HAL_RX_PREAMBLE_MAX];
|
||||
@@ -451,6 +460,8 @@ struct ath11k_rx_peer_stats {
|
||||
u64 rx_duration;
|
||||
u64 dcm_count;
|
||||
u64 ru_alloc_cnt[HAL_RX_RU_ALLOC_TYPE_MAX];
|
||||
+ struct ath11k_rx_peer_rate_stats pkt_stats;
|
||||
+ struct ath11k_rx_peer_rate_stats byte_stats;
|
||||
};
|
||||
|
||||
#define ATH11K_HE_MCS_NUM 12
|
||||
--- a/drivers/net/wireless/ath/ath11k/debugfs_sta.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/debugfs_sta.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "peer.h"
|
||||
#include "debug.h"
|
||||
#include "dp_tx.h"
|
||||
+#include "dp_rx.h"
|
||||
#include "debugfs_htt_stats.h"
|
||||
|
||||
void ath11k_debugfs_sta_add_tx_stats(struct ath11k_sta *arsta,
|
||||
@@ -248,8 +249,14 @@ static ssize_t ath11k_dbg_sta_dump_rx_st
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
struct ath11k_rx_peer_stats *rx_stats = arsta->rx_stats;
|
||||
int len = 0, i, retval = 0;
|
||||
- const int size = 4096;
|
||||
+ const int size = 4 * 4096;
|
||||
char *buf;
|
||||
+ int he_rates_avail = (rx_stats->pream_cnt[HAL_RX_PREAMBLE_11AX] > 1) ? 1 : 0;
|
||||
+ int rate_table_len = he_rates_avail ? ATH11K_RX_RATE_TABLE_11AX_NUM :
|
||||
+ ATH11K_RX_RATE_TABLE_NUM;
|
||||
+ char *legacy_rate_str[] = {"1Mbps", "2Mbps", "5.5Mbps", "6Mbps",
|
||||
+ "9Mbps", "11Mbps", "12Mbps", "18Mbps",
|
||||
+ "24Mbps", "36 Mbps", "48Mbps", "54Mbps"};
|
||||
|
||||
if (!rx_stats)
|
||||
return -ENOENT;
|
||||
@@ -280,14 +287,6 @@ static ssize_t ath11k_dbg_sta_dump_rx_st
|
||||
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,
|
||||
- "GI: 0.8us %llu 0.4us %llu 1.6us %llu 3.2us %llu\n",
|
||||
- rx_stats->gi_count[0], rx_stats->gi_count[1],
|
||||
- rx_stats->gi_count[2], rx_stats->gi_count[3]);
|
||||
- len += scnprintf(buf + len, size - len,
|
||||
- "BW: 20Mhz %llu 40Mhz %llu 80Mhz %llu 160Mhz %llu\n",
|
||||
- rx_stats->bw_count[0], rx_stats->bw_count[1],
|
||||
- rx_stats->bw_count[2], rx_stats->bw_count[3]);
|
||||
len += scnprintf(buf + len, size - len, "BCC %llu LDPC %llu\n",
|
||||
rx_stats->coding_count[0], rx_stats->coding_count[1]);
|
||||
len += scnprintf(buf + len, size - len,
|
||||
@@ -302,14 +301,96 @@ static ssize_t ath11k_dbg_sta_dump_rx_st
|
||||
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, "\nMCS(0-11) Legacy MCS(12):");
|
||||
- for (i = 0; i < HAL_RX_MAX_MCS + 1; i++)
|
||||
- len += scnprintf(buf + len, size - len, "%llu ", rx_stats->mcs_count[i]);
|
||||
- len += scnprintf(buf + len, size - len, "\nNSS(1-8):");
|
||||
- for (i = 0; i < HAL_RX_MAX_NSS; i++)
|
||||
- len += scnprintf(buf + len, size - len, "%llu ", rx_stats->nss_count[i]);
|
||||
- len += scnprintf(buf + len, size - len, "\nRX Duration:%llu ",
|
||||
+ 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\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]);
|
||||
+ 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\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]);
|
||||
+ 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\nRU: 26 %llu 52: %llu 106: %llu 242: %llu 484: %llu 996: %llu\n",
|
||||
rx_stats->dcm_count, rx_stats->ru_alloc_cnt[0],
|
||||
@@ -848,6 +929,40 @@ static const struct file_operations fops
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
+static ssize_t ath11k_dbg_sta_reset_rx_stats(struct file *file,
|
||||
+ const char __user *buf,
|
||||
+ size_t count, loff_t *ppos)
|
||||
+{
|
||||
+ struct ieee80211_sta *sta = file->private_data;
|
||||
+ struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
+ struct ath11k *ar = arsta->arvif->ar;
|
||||
+ int ret, reset;
|
||||
+
|
||||
+ if (!arsta->rx_stats)
|
||||
+ return -ENOENT;
|
||||
+
|
||||
+ ret = kstrtoint_from_user(buf, count, 0, &reset);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (!reset || reset > 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ spin_lock_bh(&ar->ab->base_lock);
|
||||
+ memset(arsta->rx_stats, 0, sizeof(*arsta->rx_stats));
|
||||
+ spin_unlock_bh(&ar->ab->base_lock);
|
||||
+
|
||||
+ ret = count;
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static const struct file_operations fops_reset_rx_stats = {
|
||||
+ .write = ath11k_dbg_sta_reset_rx_stats,
|
||||
+ .open = simple_open,
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .llseek = default_llseek,
|
||||
+};
|
||||
+
|
||||
void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, struct dentry *dir)
|
||||
{
|
||||
@@ -856,9 +971,12 @@ void ath11k_debugfs_sta_op_add(struct ie
|
||||
if (ath11k_debugfs_is_extd_tx_stats_enabled(ar))
|
||||
debugfs_create_file("tx_stats", 0400, dir, sta,
|
||||
&fops_tx_stats);
|
||||
- if (ath11k_debugfs_is_extd_rx_stats_enabled(ar))
|
||||
+ if (ath11k_debugfs_is_extd_rx_stats_enabled(ar)) {
|
||||
debugfs_create_file("rx_stats", 0400, dir, sta,
|
||||
&fops_rx_stats);
|
||||
+ debugfs_create_file("reset_rx_stats", 0600, dir, sta,
|
||||
+ &fops_reset_rx_stats);
|
||||
+ }
|
||||
|
||||
debugfs_create_file("htt_peer_stats", 0400, dir, sta,
|
||||
&fops_htt_peer_stats);
|
||||
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
|
||||
@@ -2762,10 +2762,43 @@ exit:
|
||||
return total_msdu_reaped;
|
||||
}
|
||||
|
||||
+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,
|
||||
+ u32 num_msdu)
|
||||
+{
|
||||
+ u32 rate_idx = 0;
|
||||
+ u32 mcs_idx = ppdu_info->mcs;
|
||||
+ u32 nss_idx = ppdu_info->nss - 1;
|
||||
+ 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)) {
|
||||
+ 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) {
|
||||
+ 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 {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ rx_stats->pkt_stats.rx_rate[rate_idx] += num_msdu;
|
||||
+ rx_stats->byte_stats.rx_rate[rate_idx] += ppdu_info->mpdu_len;
|
||||
+}
|
||||
+
|
||||
static void ath11k_dp_rx_update_peer_stats(struct ath11k_sta *arsta,
|
||||
struct hal_rx_mon_ppdu_info *ppdu_info)
|
||||
{
|
||||
struct ath11k_rx_peer_stats *rx_stats = arsta->rx_stats;
|
||||
+ struct ath11k *ar = arsta->arvif->ar;
|
||||
u32 num_msdu;
|
||||
int i;
|
||||
|
||||
@@ -2775,6 +2808,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);
|
||||
|
||||
+ 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;
|
||||
|
||||
@@ -2791,18 +2826,6 @@ static void ath11k_dp_rx_update_peer_sta
|
||||
ppdu_info->tid = IEEE80211_NUM_TIDS;
|
||||
}
|
||||
|
||||
- if (ppdu_info->nss > 0 && ppdu_info->nss <= HAL_RX_MAX_NSS)
|
||||
- rx_stats->nss_count[ppdu_info->nss - 1] += num_msdu;
|
||||
-
|
||||
- if (ppdu_info->mcs <= HAL_RX_MAX_MCS)
|
||||
- rx_stats->mcs_count[ppdu_info->mcs] += num_msdu;
|
||||
-
|
||||
- if (ppdu_info->gi < HAL_RX_GI_MAX)
|
||||
- rx_stats->gi_count[ppdu_info->gi] += num_msdu;
|
||||
-
|
||||
- if (ppdu_info->bw < HAL_RX_BW_MAX)
|
||||
- rx_stats->bw_count[ppdu_info->bw] += num_msdu;
|
||||
-
|
||||
if (ppdu_info->ldpc < HAL_RX_SU_MU_CODING_MAX)
|
||||
rx_stats->coding_count[ppdu_info->ldpc] += num_msdu;
|
||||
|
||||
@@ -2831,8 +2854,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;
|
||||
|
||||
- arsta->rssi_comb = ppdu_info->rssi_comb;
|
||||
-
|
||||
BUILD_BUG_ON(ARRAY_SIZE(arsta->chain_signal) >
|
||||
ARRAY_SIZE(ppdu_info->rssi_chain_pri20));
|
||||
|
||||
@@ -2841,6 +2862,52 @@ static void ath11k_dp_rx_update_peer_sta
|
||||
|
||||
rx_stats->rx_duration += ppdu_info->rx_duration;
|
||||
arsta->rx_duration = rx_stats->rx_duration;
|
||||
+
|
||||
+ if (ppdu_info->nss > 0 && ppdu_info->nss <= HAL_RX_MAX_NSS) {
|
||||
+ rx_stats->pkt_stats.nss_count[ppdu_info->nss - 1] += num_msdu;
|
||||
+ rx_stats->byte_stats.nss_count[ppdu_info->nss - 1] += ppdu_info->mpdu_len;
|
||||
+ }
|
||||
+
|
||||
+ if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11N &&
|
||||
+ ppdu_info->mcs <= HAL_RX_MAX_MCS_HT) {
|
||||
+ rx_stats->pkt_stats.ht_mcs_count[ppdu_info->mcs] += num_msdu;
|
||||
+ rx_stats->byte_stats.ht_mcs_count[ppdu_info->mcs] += ppdu_info->mpdu_len;
|
||||
+ /* To fit into rate table for HT packets */
|
||||
+ ppdu_info->mcs = ppdu_info->mcs % 8;
|
||||
+ }
|
||||
+
|
||||
+ if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11AC &&
|
||||
+ ppdu_info->mcs <= HAL_RX_MAX_MCS_VHT) {
|
||||
+ rx_stats->pkt_stats.vht_mcs_count[ppdu_info->mcs] += num_msdu;
|
||||
+ rx_stats->byte_stats.vht_mcs_count[ppdu_info->mcs] += ppdu_info->mpdu_len;
|
||||
+ }
|
||||
+
|
||||
+ if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11AX &&
|
||||
+ ppdu_info->mcs <= HAL_RX_MAX_MCS_HE) {
|
||||
+ rx_stats->pkt_stats.he_mcs_count[ppdu_info->mcs] += num_msdu;
|
||||
+ rx_stats->byte_stats.he_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) {
|
||||
+ rx_stats->pkt_stats.legacy_count[ppdu_info->rate] += num_msdu;
|
||||
+ rx_stats->byte_stats.legacy_count[ppdu_info->rate] += ppdu_info->mpdu_len;
|
||||
+ }
|
||||
+
|
||||
+ if (ppdu_info->gi < HAL_RX_GI_MAX) {
|
||||
+ rx_stats->pkt_stats.gi_count[ppdu_info->gi] += num_msdu;
|
||||
+ rx_stats->byte_stats.gi_count[ppdu_info->gi] += ppdu_info->mpdu_len;
|
||||
+ }
|
||||
+
|
||||
+ if (ppdu_info->bw < HAL_RX_BW_MAX) {
|
||||
+ rx_stats->pkt_stats.bw_count[ppdu_info->bw] += num_msdu;
|
||||
+ rx_stats->byte_stats.bw_count[ppdu_info->bw] += ppdu_info->mpdu_len;
|
||||
+ }
|
||||
+
|
||||
+ ath11k_dp_rx_update_peer_rate_table_stats(rx_stats, ppdu_info, num_msdu);
|
||||
+
|
||||
}
|
||||
|
||||
static struct sk_buff *ath11k_dp_rx_alloc_mon_status_buf(struct ath11k_base *ab,
|
||||
--- a/drivers/net/wireless/ath/ath11k/dp_rx.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.h
|
||||
@@ -42,6 +42,25 @@ struct ath11k_dp_rfc1042_hdr {
|
||||
__be16 snap_type;
|
||||
} __packed;
|
||||
|
||||
+static inline u32 ath11k_he_gi_to_nl80211_he_gi(u8 sgi)
|
||||
+{
|
||||
+ u32 ret = 0;
|
||||
+
|
||||
+ switch (sgi) {
|
||||
+ case RX_MSDU_START_SGI_0_8_US:
|
||||
+ ret = NL80211_RATE_INFO_HE_GI_0_8;
|
||||
+ break;
|
||||
+ case RX_MSDU_START_SGI_1_6_US:
|
||||
+ ret = NL80211_RATE_INFO_HE_GI_1_6;
|
||||
+ break;
|
||||
+ case RX_MSDU_START_SGI_3_2_US:
|
||||
+ ret = NL80211_RATE_INFO_HE_GI_3_2;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
int ath11k_dp_rx_ampdu_start(struct ath11k *ar,
|
||||
struct ieee80211_ampdu_params *params);
|
||||
int ath11k_dp_rx_ampdu_stop(struct ath11k *ar,
|
||||
--- a/drivers/net/wireless/ath/ath11k/hal_rx.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/hal_rx.c
|
||||
@@ -976,44 +976,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);
|
||||
- ppdu_info->gi = info1 & HAL_RX_HT_SIG_INFO_INFO1_GI;
|
||||
-
|
||||
- switch (ppdu_info->mcs) {
|
||||
- case 0 ... 7:
|
||||
- ppdu_info->nss = 1;
|
||||
- break;
|
||||
- case 8 ... 15:
|
||||
- ppdu_info->nss = 2;
|
||||
- break;
|
||||
- case 16 ... 23:
|
||||
- ppdu_info->nss = 3;
|
||||
- break;
|
||||
- case 24 ... 31:
|
||||
- ppdu_info->nss = 4;
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- if (ppdu_info->nss > 1)
|
||||
- ppdu_info->mcs = ppdu_info->mcs % 8;
|
||||
-
|
||||
+ ppdu_info->gi = FIELD_GET(HAL_RX_HT_SIG_INFO_INFO1_GI, info1);
|
||||
+ ppdu_info->nss = (ppdu_info->mcs >> 3) + 1;
|
||||
ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_SU;
|
||||
break;
|
||||
}
|
||||
case HAL_PHYRX_L_SIG_B: {
|
||||
struct hal_rx_lsig_b_info *lsigb =
|
||||
(struct hal_rx_lsig_b_info *)tlv_data;
|
||||
+ u8 rate;
|
||||
+
|
||||
+ rate = FIELD_GET(HAL_RX_LSIG_B_INFO_INFO0_RATE,
|
||||
+ __le32_to_cpu(lsigb->info0));
|
||||
|
||||
- ppdu_info->rate = FIELD_GET(HAL_RX_LSIG_B_INFO_INFO0_RATE,
|
||||
- __le32_to_cpu(lsigb->info0));
|
||||
+ switch (rate) {
|
||||
+ case 1:
|
||||
+ rate = HAL_RX_LEGACY_RATE_1_MBPS;
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ case 5:
|
||||
+ rate = HAL_RX_LEGACY_RATE_2_MBPS;
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ case 6:
|
||||
+ rate = HAL_RX_LEGACY_RATE_5_5_MBPS;
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ case 7:
|
||||
+ rate = HAL_RX_LEGACY_RATE_11_MBPS;
|
||||
+ break;
|
||||
+ default:
|
||||
+ rate = HAL_RX_LEGACY_RATE_INVALID;
|
||||
+ }
|
||||
+ ppdu_info->rate = rate;
|
||||
ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_SU;
|
||||
break;
|
||||
}
|
||||
case HAL_PHYRX_L_SIG_A: {
|
||||
struct hal_rx_lsig_a_info *lsiga =
|
||||
(struct hal_rx_lsig_a_info *)tlv_data;
|
||||
+ u8 rate;
|
||||
|
||||
- ppdu_info->rate = FIELD_GET(HAL_RX_LSIG_A_INFO_INFO0_RATE,
|
||||
- __le32_to_cpu(lsiga->info0));
|
||||
+ rate = FIELD_GET(HAL_RX_LSIG_A_INFO_INFO0_RATE,
|
||||
+ __le32_to_cpu(lsiga->info0));
|
||||
+ switch (rate) {
|
||||
+ case 8:
|
||||
+ rate = HAL_RX_LEGACY_RATE_48_MBPS;
|
||||
+ break;
|
||||
+ case 9:
|
||||
+ rate = HAL_RX_LEGACY_RATE_24_MBPS;
|
||||
+ break;
|
||||
+ case 10:
|
||||
+ rate = HAL_RX_LEGACY_RATE_12_MBPS;
|
||||
+ break;
|
||||
+ case 11:
|
||||
+ rate = HAL_RX_LEGACY_RATE_6_MBPS;
|
||||
+ break;
|
||||
+ case 12:
|
||||
+ rate = HAL_RX_LEGACY_RATE_54_MBPS;
|
||||
+ break;
|
||||
+ case 13:
|
||||
+ rate = HAL_RX_LEGACY_RATE_36_MBPS;
|
||||
+ break;
|
||||
+ case 14:
|
||||
+ rate = HAL_RX_LEGACY_RATE_18_MBPS;
|
||||
+ break;
|
||||
+ case 15:
|
||||
+ rate = HAL_RX_LEGACY_RATE_9_MBPS;
|
||||
+ break;
|
||||
+ default:
|
||||
+ rate = HAL_RX_LEGACY_RATE_INVALID;
|
||||
+ }
|
||||
+ ppdu_info->rate = rate;
|
||||
ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_SU;
|
||||
break;
|
||||
}
|
||||
@@ -1471,6 +1505,9 @@ ath11k_hal_rx_parse_mon_status_tlv(struc
|
||||
peer_id = ath11k_hal_rx_mpduinfo_get_peerid(ab, mpdu_info);
|
||||
if (peer_id)
|
||||
ppdu_info->peer_id = peer_id;
|
||||
+
|
||||
+ ppdu_info->mpdu_len += ab->hw_params.hw_ops->rx_desc_get_hal_mpdu_len(mpdu_info);
|
||||
+
|
||||
break;
|
||||
}
|
||||
case HAL_RXPCU_PPDU_END_INFO: {
|
||||
--- a/drivers/net/wireless/ath/ath11k/hal_rx.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/hal_rx.h
|
||||
@@ -20,7 +20,11 @@ struct hal_rx_wbm_rel_info {
|
||||
#define VHT_SIG_SU_NSS_MASK 0x7
|
||||
|
||||
#define HAL_RX_MAX_MCS 12
|
||||
+#define HAL_RX_MAX_MCS_HT 31
|
||||
+#define HAL_RX_MAX_MCS_VHT 9
|
||||
+#define HAL_RX_MAX_MCS_HE 11
|
||||
#define HAL_RX_MAX_NSS 8
|
||||
+#define HAL_RX_MAX_NUM_LEGACY_RATES 12
|
||||
|
||||
struct hal_rx_mon_status_tlv_hdr {
|
||||
u32 hdr;
|
||||
@@ -104,6 +108,22 @@ struct hal_rx_user_status {
|
||||
u32 mpdu_err_byte_count;
|
||||
};
|
||||
|
||||
+enum hal_rx_legacy_rate {
|
||||
+ HAL_RX_LEGACY_RATE_1_MBPS,
|
||||
+ HAL_RX_LEGACY_RATE_2_MBPS,
|
||||
+ HAL_RX_LEGACY_RATE_5_5_MBPS,
|
||||
+ HAL_RX_LEGACY_RATE_6_MBPS,
|
||||
+ HAL_RX_LEGACY_RATE_9_MBPS,
|
||||
+ HAL_RX_LEGACY_RATE_11_MBPS,
|
||||
+ HAL_RX_LEGACY_RATE_12_MBPS,
|
||||
+ HAL_RX_LEGACY_RATE_18_MBPS,
|
||||
+ HAL_RX_LEGACY_RATE_24_MBPS,
|
||||
+ HAL_RX_LEGACY_RATE_36_MBPS,
|
||||
+ HAL_RX_LEGACY_RATE_48_MBPS,
|
||||
+ HAL_RX_LEGACY_RATE_54_MBPS,
|
||||
+ HAL_RX_LEGACY_RATE_INVALID,
|
||||
+};
|
||||
+
|
||||
#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
|
||||
@@ -128,6 +148,7 @@ struct hal_rx_mon_ppdu_info {
|
||||
u32 num_mpdu_fcs_ok;
|
||||
u32 num_mpdu_fcs_err;
|
||||
u32 preamble_type;
|
||||
+ u32 mpdu_len;
|
||||
u16 chan_num;
|
||||
u16 tcp_msdu_count;
|
||||
u16 tcp_ack_msdu_count;
|
||||
--- a/drivers/net/wireless/ath/ath11k/hw.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/hw.c
|
||||
@@ -900,6 +900,17 @@ static u32 ath11k_hw_wcn6750_get_tcl_rin
|
||||
return skb_get_hash(skb);
|
||||
}
|
||||
|
||||
+static u32 ath11k_hw_ipq8074_rx_desc_get_hal_mpdu_len(struct hal_rx_mpdu_info *mpdu_info)
|
||||
+{
|
||||
+ return FIELD_GET(HAL_RX_MPDU_INFO_INFO1_MPDU_LEN,
|
||||
+ __le32_to_cpu(mpdu_info->u.ipq8074.info1));
|
||||
+}
|
||||
+
|
||||
+static u32 ath11k_hw_qcn9074_rx_desc_get_hal_mpdu_len(struct hal_rx_mpdu_info *mpdu_info)
|
||||
+{
|
||||
+ return FIELD_GET(HAL_RX_MPDU_INFO_INFO1_MPDU_LEN,
|
||||
+ __le32_to_cpu(mpdu_info->u.qcn9074.info1));
|
||||
+}
|
||||
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,
|
||||
@@ -938,6 +949,7 @@ const struct ath11k_hw_ops ipq8074_ops =
|
||||
.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,
|
||||
.get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector,
|
||||
+ .rx_desc_get_hal_mpdu_len = ath11k_hw_ipq8074_rx_desc_get_hal_mpdu_len,
|
||||
};
|
||||
|
||||
const struct ath11k_hw_ops ipq6018_ops = {
|
||||
@@ -978,6 +990,7 @@ const struct ath11k_hw_ops ipq6018_ops =
|
||||
.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,
|
||||
.get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector,
|
||||
+ .rx_desc_get_hal_mpdu_len = ath11k_hw_ipq8074_rx_desc_get_hal_mpdu_len,
|
||||
};
|
||||
|
||||
const struct ath11k_hw_ops qca6390_ops = {
|
||||
@@ -1018,6 +1031,7 @@ const struct ath11k_hw_ops qca6390_ops =
|
||||
.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,
|
||||
.get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector,
|
||||
+ .rx_desc_get_hal_mpdu_len = ath11k_hw_ipq8074_rx_desc_get_hal_mpdu_len,
|
||||
};
|
||||
|
||||
const struct ath11k_hw_ops qcn9074_ops = {
|
||||
@@ -1058,6 +1072,7 @@ const struct ath11k_hw_ops qcn9074_ops =
|
||||
.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,
|
||||
.get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector,
|
||||
+ .rx_desc_get_hal_mpdu_len = ath11k_hw_qcn9074_rx_desc_get_hal_mpdu_len,
|
||||
};
|
||||
|
||||
const struct ath11k_hw_ops wcn6855_ops = {
|
||||
@@ -1098,6 +1113,7 @@ const struct ath11k_hw_ops wcn6855_ops =
|
||||
.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,
|
||||
.get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector,
|
||||
+ .rx_desc_get_hal_mpdu_len = ath11k_hw_ipq8074_rx_desc_get_hal_mpdu_len,
|
||||
};
|
||||
|
||||
const struct ath11k_hw_ops wcn6750_ops = {
|
||||
@@ -1179,6 +1195,7 @@ const struct ath11k_hw_ops ipq5018_ops =
|
||||
.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,
|
||||
.get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector,
|
||||
+ .rx_desc_get_hal_mpdu_len = ath11k_hw_qcn9074_rx_desc_get_hal_mpdu_len,
|
||||
};
|
||||
|
||||
#define ATH11K_TX_RING_MASK_0 BIT(0)
|
||||
--- a/drivers/net/wireless/ath/ath11k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/hw.h
|
||||
@@ -276,6 +276,7 @@ struct ath11k_hw_ops {
|
||||
bool (*rx_desc_mac_addr2_valid)(struct hal_rx_desc *desc);
|
||||
u8* (*rx_desc_mpdu_start_addr2)(struct hal_rx_desc *desc);
|
||||
u32 (*get_ring_selector)(struct sk_buff *skb);
|
||||
+ u32 (*rx_desc_get_hal_mpdu_len)(struct hal_rx_mpdu_info *mpdu_info);
|
||||
};
|
||||
|
||||
extern const struct ath11k_hw_ops ipq8074_ops;
|
||||
@ -0,0 +1,774 @@
|
||||
From e4f16128c53b48f166301085cecc23f77bf3ff8e Mon Sep 17 00:00:00 2001
|
||||
From: Miles Hu <milehu@codeaurora.org>
|
||||
Date: Fri, 11 Oct 2019 19:24:06 -0700
|
||||
Subject: [PATCH] ath11k: add HE stats in peer stats packet counters for MIMO
|
||||
and OFDMA
|
||||
|
||||
Signed-off-by: Miles Hu <milehu@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/core.h | 23 ++++-
|
||||
drivers/net/wireless/ath/ath11k/debugfs_sta.c | 127 +++++++++++++++++++++++++-
|
||||
drivers/net/wireless/ath/ath11k/dp.h | 21 ++++-
|
||||
drivers/net/wireless/ath/ath11k/dp_rx.c | 17 +++-
|
||||
drivers/net/wireless/ath/ath11k/rx_desc.h | 5 +
|
||||
5 files changed, 185 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/core.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "dbring.h"
|
||||
#include "spectral.h"
|
||||
#include "wow.h"
|
||||
+#include "rx_desc.h"
|
||||
#include "fw.h"
|
||||
|
||||
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
|
||||
@@ -522,6 +523,8 @@ struct ath11k_htt_data_stats {
|
||||
u64 bw[ATH11K_COUNTER_TYPE_MAX][ATH11K_BW_NUM];
|
||||
u64 nss[ATH11K_COUNTER_TYPE_MAX][ATH11K_NSS_NUM];
|
||||
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];
|
||||
};
|
||||
|
||||
struct ath11k_htt_tx_stats {
|
||||
@@ -529,6 +532,9 @@ struct ath11k_htt_tx_stats {
|
||||
u64 tx_duration;
|
||||
u64 ba_fails;
|
||||
u64 ack_fails;
|
||||
+ u16 ru_start;
|
||||
+ u16 ru_tones;
|
||||
+ u32 mu_group[MAX_MU_GROUP_ID];
|
||||
};
|
||||
|
||||
struct ath11k_per_ppdu_tx_stats {
|
||||
@@ -645,11 +651,16 @@ struct ath11k_per_peer_tx_stats {
|
||||
u32 succ_bytes;
|
||||
u32 retry_bytes;
|
||||
u32 failed_bytes;
|
||||
+ u32 duration;
|
||||
u16 succ_pkts;
|
||||
u16 retry_pkts;
|
||||
u16 failed_pkts;
|
||||
- u32 duration;
|
||||
+ u16 ru_start;
|
||||
+ u16 ru_tones;
|
||||
u8 ba_fails;
|
||||
+ u8 ppdu_type;
|
||||
+ u32 mu_grpid;
|
||||
+ u32 mu_pos;
|
||||
bool is_ampdu;
|
||||
};
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/debugfs_sta.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/debugfs_sta.c
|
||||
@@ -14,13 +14,39 @@
|
||||
#include "dp_rx.h"
|
||||
#include "debugfs_htt_stats.h"
|
||||
|
||||
+static inline u32 ath11k_he_tones_in_ru_to_nl80211_he_ru_alloc(u16 ru_tones)
|
||||
+{
|
||||
+ u32 ret = 0;
|
||||
+ switch (ru_tones) {
|
||||
+ case 26:
|
||||
+ ret = NL80211_RATE_INFO_HE_RU_ALLOC_26;
|
||||
+ break;
|
||||
+ case 52:
|
||||
+ ret = NL80211_RATE_INFO_HE_RU_ALLOC_52;
|
||||
+ break;
|
||||
+ case 106:
|
||||
+ ret = NL80211_RATE_INFO_HE_RU_ALLOC_106;
|
||||
+ break;
|
||||
+ case 242:
|
||||
+ ret = NL80211_RATE_INFO_HE_RU_ALLOC_242;
|
||||
+ break;
|
||||
+ case 484:
|
||||
+ ret = NL80211_RATE_INFO_HE_RU_ALLOC_484;
|
||||
+ break;
|
||||
+ case 996:
|
||||
+ ret = NL80211_RATE_INFO_HE_RU_ALLOC_996;
|
||||
+ break;
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
void ath11k_debugfs_sta_add_tx_stats(struct ath11k_sta *arsta,
|
||||
struct ath11k_per_peer_tx_stats *peer_stats,
|
||||
u8 legacy_rate_idx)
|
||||
{
|
||||
struct rate_info *txrate = &arsta->txrate;
|
||||
struct ath11k_htt_tx_stats *tx_stats;
|
||||
- int gi, mcs, bw, nss;
|
||||
+ int gi, mcs, bw, nss, ru_type, ppdu_type;
|
||||
|
||||
if (!arsta->tx_stats)
|
||||
return;
|
||||
@@ -65,6 +91,43 @@ void ath11k_debugfs_sta_add_tx_stats(str
|
||||
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;
|
||||
|
||||
@@ -125,6 +188,17 @@ void ath11k_debugfs_sta_add_tx_stats(str
|
||||
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 ath11k_debugfs_sta_update_txcompl(struct ath11k *ar,
|
||||
@@ -141,12 +215,13 @@ static ssize_t ath11k_dbg_sta_dump_tx_st
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
struct ath11k_htt_data_stats *stats;
|
||||
- static const char *str_name[ATH11K_STATS_TYPE_MAX] = {"succ", "fail",
|
||||
+ static const char *str_name[ATH11K_STATS_TYPE_MAX] = {"success", "fail",
|
||||
"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;
|
||||
- char *buf;
|
||||
+ char *buf, mu_group_id[MAX_MU_GROUP_LENGTH] = {0};
|
||||
+ u32 index;
|
||||
|
||||
if (!arsta->tx_stats)
|
||||
return -ENOENT;
|
||||
@@ -164,45 +239,46 @@ static ssize_t ath11k_dbg_sta_dump_tx_st
|
||||
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",
|
||||
+ " HE MCS %s\n\t",
|
||||
str[j]);
|
||||
for (i = 0; i < ATH11K_HE_MCS_NUM; i++)
|
||||
len += scnprintf(buf + len, size - len,
|
||||
- " %llu ",
|
||||
+ "%llu ",
|
||||
stats->he[j][i]);
|
||||
len += scnprintf(buf + len, size - len, "\n");
|
||||
len += scnprintf(buf + len, size - len,
|
||||
- " VHT MCS %s\n",
|
||||
+ " VHT MCS %s\n\t",
|
||||
str[j]);
|
||||
for (i = 0; i < ATH11K_VHT_MCS_NUM; i++)
|
||||
len += scnprintf(buf + len, size - len,
|
||||
- " %llu ",
|
||||
+ "%llu ",
|
||||
stats->vht[j][i]);
|
||||
len += scnprintf(buf + len, size - len, "\n");
|
||||
- len += scnprintf(buf + len, size - len, " HT MCS %s\n",
|
||||
+ len += scnprintf(buf + len, size - len, " HT MCS %s\n\t",
|
||||
str[j]);
|
||||
for (i = 0; i < ATH11K_HT_MCS_NUM; i++)
|
||||
len += scnprintf(buf + len, size - len,
|
||||
- " %llu ", stats->ht[j][i]);
|
||||
+ "%llu ", stats->ht[j][i]);
|
||||
len += scnprintf(buf + len, size - len, "\n");
|
||||
len += scnprintf(buf + len, size - len,
|
||||
" BW %s (20,40,80,160 MHz)\n", str[j]);
|
||||
len += scnprintf(buf + len, size - len,
|
||||
- " %llu %llu %llu %llu\n",
|
||||
+ "\t%llu %llu %llu %llu\n",
|
||||
stats->bw[j][0], stats->bw[j][1],
|
||||
stats->bw[j][2], stats->bw[j][3]);
|
||||
len += scnprintf(buf + len, size - len,
|
||||
" NSS %s (1x1,2x2,3x3,4x4)\n", str[j]);
|
||||
len += scnprintf(buf + len, size - len,
|
||||
- " %llu %llu %llu %llu\n",
|
||||
+ "\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,
|
||||
- " %llu %llu %llu %llu\n",
|
||||
+ "\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,
|
||||
@@ -211,10 +287,68 @@ static ssize_t ath11k_dbg_sta_dump_tx_st
|
||||
for (i = 0; i < ATH11K_LEGACY_NUM; i++)
|
||||
len += scnprintf(buf + len, size - len, "%llu ",
|
||||
stats->legacy[j][i]);
|
||||
- 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]);
|
||||
+ 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 == ATH11K_STATS_TYPE_FAIL ||
|
||||
+ k == ATH11K_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);
|
||||
@@ -222,6 +356,7 @@ static ssize_t ath11k_dbg_sta_dump_tx_st
|
||||
"BA fails\n %llu\n", arsta->tx_stats->ba_fails);
|
||||
len += scnprintf(buf + len, size - len,
|
||||
"ack fails\n %llu\n", arsta->tx_stats->ack_fails);
|
||||
+
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
if (len > size)
|
||||
--- a/drivers/net/wireless/ath/ath11k/dp.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/dp.h
|
||||
@@ -601,6 +601,45 @@ enum htt_ppdu_stats_tag_type {
|
||||
BIT(HTT_PPDU_STATS_TAG_TX_MGMTCTRL_PAYLOAD) | \
|
||||
HTT_PPDU_STATS_TAG_DEFAULT)
|
||||
|
||||
+#define HTT_STATS_FRAMECTRL_TYPE_MASK 0x0C
|
||||
+#define HTT_STATS_GET_FRAME_CTRL_TYPE(_val) \
|
||||
+ (((_val) & HTT_STATS_FRAMECTRL_TYPE_MASK) >> 2)
|
||||
+#define HTT_STATS_FRAME_CTRL_TYPE_MGMT 0x0
|
||||
+#define HTT_STATS_FRAME_CTRL_TYPE_CTRL 0x1
|
||||
+#define HTT_STATS_FRAME_CTRL_TYPE_DATA 0x2
|
||||
+#define HTT_STATS_FRAME_CTRL_TYPE_RESV 0x3
|
||||
+
|
||||
+enum htt_stats_frametype {
|
||||
+ HTT_STATS_FTYPE_SGEN_NDPA = 0,
|
||||
+ HTT_STATS_FTYPE_SGEN_NDP,
|
||||
+ HTT_STATS_FTYPE_SGEN_BRP,
|
||||
+ HTT_STATS_FTYPE_SGEN_BAR,
|
||||
+ HTT_STATS_FTYPE_SGEN_RTS,
|
||||
+ HTT_STATS_FTYPE_SGEN_CTS,
|
||||
+ HTT_STATS_FTYPE_SGEN_CFEND,
|
||||
+ HTT_STATS_FTYPE_SGEN_AX_NDPA,
|
||||
+ HTT_STATS_FTYPE_SGEN_AX_NDP,
|
||||
+ HTT_STATS_FTYPE_SGEN_MU_TRIG,
|
||||
+ HTT_STATS_FTYPE_SGEN_MU_BAR,
|
||||
+ HTT_STATS_FTYPE_SGEN_MU_BRP,
|
||||
+ HTT_STATS_FTYPE_SGEN_MU_RTS,
|
||||
+ HTT_STATS_FTYPE_SGEN_MU_BSR,
|
||||
+ HTT_STATS_FTYPE_SGEN_UL_BSR,
|
||||
+ HTT_STATS_FTYPE_SGEN_UL_BSR_TRIGGER = HTT_STATS_FTYPE_SGEN_UL_BSR,
|
||||
+ HTT_STATS_FTYPE_TIDQ_DATA_SU,
|
||||
+ HTT_STATS_FTYPE_TIDQ_DATA_MU,
|
||||
+ HTT_STATS_FTYPE_SGEN_UL_BSR_RESP,
|
||||
+ HTT_STATS_FTYPE_SGEN_QOS_NULL,
|
||||
+ HTT_STATS_FTYPE_MAX,
|
||||
+};
|
||||
+
|
||||
+enum htt_stats_internal_ppdu_frametype {
|
||||
+ HTT_STATS_PPDU_FTYPE_CTRL,
|
||||
+ HTT_STATS_PPDU_FTYPE_DATA,
|
||||
+ HTT_STATS_PPDU_FTYPE_BAR,
|
||||
+ HTT_STATS_PPDU_FTYPE_MAX
|
||||
+};
|
||||
+
|
||||
/* HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG Message
|
||||
*
|
||||
* details:
|
||||
@@ -1240,6 +1279,19 @@ 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)
|
||||
|
||||
+enum HTT_PPDU_STATS_PPDU_TYPE {
|
||||
+ HTT_PPDU_STATS_PPDU_TYPE_SU,
|
||||
+ HTT_PPDU_STATS_PPDU_TYPE_MU_MIMO,
|
||||
+ HTT_PPDU_STATS_PPDU_TYPE_MU_OFDMA,
|
||||
+ HTT_PPDU_STATS_PPDU_TYPE_MU_MIMO_OFDMA,
|
||||
+ HTT_PPDU_STATS_PPDU_TYPE_UL_TRIG,
|
||||
+ HTT_PPDU_STATS_PPDU_TYPE_BURST_BCN,
|
||||
+ HTT_PPDU_STATS_PPDU_TYPE_UL_BSR_RESP,
|
||||
+ HTT_PPDU_STATS_PPDU_TYPE_UL_BSR_TRIG,
|
||||
+ HTT_PPDU_STATS_PPDU_TYPE_UL_RESP,
|
||||
+ HTT_PPDU_STATS_PPDU_TYPE_MAX
|
||||
+};
|
||||
+
|
||||
#define HTT_PPDU_STATS_USER_RATE_INFO1_RESP_TYPE_VALD_M BIT(0)
|
||||
#define HTT_PPDU_STATS_USER_RATE_INFO1_PPDU_TYPE_M GENMASK(5, 1)
|
||||
|
||||
@@ -1267,6 +1319,12 @@ enum htt_ppdu_stats_gi {
|
||||
FIELD_GET(HTT_PPDU_STATS_USER_RATE_FLAGS_GI_M, _val)
|
||||
#define HTT_USR_RATE_DCM(_val) \
|
||||
FIELD_GET(HTT_PPDU_STATS_USER_RATE_FLAGS_DCM_M, _val)
|
||||
+#define HTT_USR_RATE_PPDU_TYPE(_val) \
|
||||
+ FIELD_GET(HTT_PPDU_STATS_USER_RATE_INFO1_PPDU_TYPE_M, _val)
|
||||
+#define HTT_USR_RATE_MU_GRPID(_val) \
|
||||
+ FIELD_GET(HTT_PPDU_STATS_USER_RATE_INFO0_MU_GROUP_ID_M, _val)
|
||||
+#define HTT_USR_RATE_USR_POS(_val) \
|
||||
+ FIELD_GET(HTT_PPDU_STATS_USER_RATE_INFO0_USER_POS_M, _val)
|
||||
|
||||
#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)
|
||||
@@ -1358,16 +1416,33 @@ struct htt_ppdu_stats_usr_cmpltn_ack_ba_
|
||||
u32 success_bytes;
|
||||
} __packed;
|
||||
|
||||
+#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)
|
||||
+
|
||||
+struct htt_ppdu_stats_user_common {
|
||||
+ u8 tid_num;
|
||||
+ u8 vdev_id;
|
||||
+ u16 sw_peer_id;
|
||||
+ u32 info;
|
||||
+ u32 ctrl;
|
||||
+ u32 buffer_paddr_31_0;
|
||||
+ u32 buffer_paddr_39_32;
|
||||
+ u32 host_opaque_cookie;
|
||||
+} __packed;
|
||||
+
|
||||
struct htt_ppdu_user_stats {
|
||||
u16 peer_id;
|
||||
+ u16 delay_ba;
|
||||
u32 tlv_flags;
|
||||
bool is_valid_peer_id;
|
||||
struct htt_ppdu_stats_user_rate rate;
|
||||
struct htt_ppdu_stats_usr_cmpltn_cmn cmpltn_cmn;
|
||||
struct htt_ppdu_stats_usr_cmpltn_ack_ba_status ack_ba;
|
||||
+ struct htt_ppdu_stats_user_common common;
|
||||
};
|
||||
|
||||
-#define HTT_PPDU_STATS_MAX_USERS 8
|
||||
+#define HTT_PPDU_STATS_MAX_USERS 37
|
||||
#define HTT_PPDU_DESC_MAX_DEPTH 16
|
||||
|
||||
struct htt_ppdu_stats {
|
||||
@@ -1376,7 +1451,7 @@ struct htt_ppdu_stats {
|
||||
};
|
||||
|
||||
struct htt_ppdu_stats_info {
|
||||
- u32 ppdu_id;
|
||||
+ u32 tlv_bitmap, ppdu_id, frame_type, frame_ctrl, delay_ba, bar_num_users;
|
||||
struct htt_ppdu_stats ppdu_stats;
|
||||
struct list_head list;
|
||||
};
|
||||
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
|
||||
@@ -1253,9 +1253,10 @@ static int ath11k_htt_tlv_ppdu_stats_par
|
||||
void *data)
|
||||
{
|
||||
struct htt_ppdu_stats_info *ppdu_info;
|
||||
- struct htt_ppdu_user_stats *user_stats;
|
||||
+ struct htt_ppdu_user_stats *user_stats = NULL;
|
||||
int cur_user;
|
||||
u16 peer_id;
|
||||
+ u32 frame_type;
|
||||
|
||||
ppdu_info = data;
|
||||
|
||||
@@ -1268,6 +1269,26 @@ static int ath11k_htt_tlv_ppdu_stats_par
|
||||
}
|
||||
memcpy((void *)&ppdu_info->ppdu_stats.common, ptr,
|
||||
sizeof(struct htt_ppdu_stats_common));
|
||||
+ frame_type =
|
||||
+ FIELD_GET(HTT_PPDU_STATS_CMN_FLAGS_FRAME_TYPE_M,
|
||||
+ ppdu_info->ppdu_stats.common.flags);
|
||||
+ switch (frame_type) {
|
||||
+ case HTT_STATS_FTYPE_TIDQ_DATA_SU:
|
||||
+ case HTT_STATS_FTYPE_TIDQ_DATA_MU:
|
||||
+ if (HTT_STATS_GET_FRAME_CTRL_TYPE(ppdu_info->frame_ctrl) <= HTT_STATS_FRAME_CTRL_TYPE_CTRL)
|
||||
+ ppdu_info->frame_type = HTT_STATS_PPDU_FTYPE_CTRL;
|
||||
+ else
|
||||
+ ppdu_info->frame_type = HTT_STATS_PPDU_FTYPE_DATA;
|
||||
+ break;
|
||||
+ case HTT_STATS_FTYPE_SGEN_MU_BAR:
|
||||
+ case HTT_STATS_FTYPE_SGEN_BAR:
|
||||
+ ppdu_info->frame_type = HTT_STATS_PPDU_FTYPE_BAR;
|
||||
+ break;
|
||||
+ default:
|
||||
+ ppdu_info->frame_type = HTT_STATS_PPDU_FTYPE_CTRL;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
break;
|
||||
case HTT_PPDU_STATS_TAG_USR_RATE:
|
||||
if (len < sizeof(struct htt_ppdu_stats_user_rate)) {
|
||||
@@ -1300,6 +1321,7 @@ static int ath11k_htt_tlv_ppdu_stats_par
|
||||
peer_id);
|
||||
if (cur_user < 0)
|
||||
return -EINVAL;
|
||||
+ ppdu_info->bar_num_users += 1;
|
||||
user_stats = &ppdu_info->ppdu_stats.user_stats[cur_user];
|
||||
user_stats->peer_id = peer_id;
|
||||
user_stats->is_valid_peer_id = true;
|
||||
@@ -1328,44 +1350,30 @@ static int ath11k_htt_tlv_ppdu_stats_par
|
||||
sizeof(struct htt_ppdu_stats_usr_cmpltn_ack_ba_status));
|
||||
user_stats->tlv_flags |= BIT(tag);
|
||||
break;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-int ath11k_dp_htt_tlv_iter(struct ath11k_base *ab, const void *ptr, size_t len,
|
||||
- int (*iter)(struct ath11k_base *ar, u16 tag, u16 len,
|
||||
- const void *ptr, void *data),
|
||||
- void *data)
|
||||
-{
|
||||
- const struct htt_tlv *tlv;
|
||||
- const void *begin = ptr;
|
||||
- u16 tlv_tag, tlv_len;
|
||||
- int ret = -EINVAL;
|
||||
-
|
||||
- while (len > 0) {
|
||||
- if (len < sizeof(*tlv)) {
|
||||
- ath11k_err(ab, "htt tlv parse failure at byte %zd (%zu bytes left, %zu expected)\n",
|
||||
- ptr - begin, len, sizeof(*tlv));
|
||||
+ case HTT_PPDU_STATS_TAG_USR_COMMON:
|
||||
+ if (len < sizeof(struct htt_ppdu_stats_user_common)) {
|
||||
+ ath11k_warn(ab, "Invalid len %d for the tag 0x%x\n",
|
||||
+ len, tag);
|
||||
return -EINVAL;
|
||||
}
|
||||
- tlv = (struct htt_tlv *)ptr;
|
||||
- tlv_tag = FIELD_GET(HTT_TLV_TAG, tlv->header);
|
||||
- tlv_len = FIELD_GET(HTT_TLV_LEN, tlv->header);
|
||||
- ptr += sizeof(*tlv);
|
||||
- len -= sizeof(*tlv);
|
||||
-
|
||||
- if (tlv_len > len) {
|
||||
- ath11k_err(ab, "htt tlv parse failure of tag %u at byte %zd (%zu bytes left, %u expected)\n",
|
||||
- tlv_tag, ptr - begin, len, tlv_len);
|
||||
+ peer_id = ((struct htt_ppdu_stats_user_common *)ptr)->sw_peer_id;
|
||||
+ cur_user = ath11k_get_ppdu_user_index(&ppdu_info->ppdu_stats,
|
||||
+ peer_id);
|
||||
+ if (cur_user < 0)
|
||||
return -EINVAL;
|
||||
- }
|
||||
- ret = iter(ab, tlv_tag, tlv_len, ptr, data);
|
||||
- if (ret == -ENOMEM)
|
||||
- return ret;
|
||||
-
|
||||
- ptr += tlv_len;
|
||||
- len -= tlv_len;
|
||||
+ user_stats = &ppdu_info->ppdu_stats.user_stats[cur_user];
|
||||
+ memcpy(&user_stats->common, ptr,
|
||||
+ sizeof(struct htt_ppdu_stats_user_common));
|
||||
+ ppdu_info->frame_ctrl = FIELD_GET(HTT_PPDU_STATS_USR_CMN_CTL_FRM_CTRL,
|
||||
+ user_stats->common.ctrl);
|
||||
+ user_stats->delay_ba = FIELD_GET(HTT_PPDU_STATS_USR_CMN_FLAG_DELAYBA,
|
||||
+ user_stats->common.info);
|
||||
+ ppdu_info->delay_ba = user_stats->delay_ba;
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
}
|
||||
+ ppdu_info->tlv_bitmap |= BIT(tag);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1383,8 +1391,8 @@ ath11k_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;
|
||||
- u16 rate = 0, succ_pkts = 0;
|
||||
+ u32 succ_bytes = 0, ppdu_type, mu_grpid, mu_pos;
|
||||
+ u16 rate = 0, succ_pkts = 0, ru_tone, ru_start;
|
||||
u32 tx_duration = 0;
|
||||
u8 tid = HTT_PPDU_STATS_NON_QOS_TID;
|
||||
bool is_ampdu = false;
|
||||
@@ -1415,6 +1423,11 @@ ath11k_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);
|
||||
+ ppdu_type = HTT_USR_RATE_PPDU_TYPE(user_rate->info1);
|
||||
+ mu_grpid = HTT_USR_RATE_MU_GRPID(user_rate->info0);
|
||||
+ mu_pos = HTT_USR_RATE_USR_POS(user_rate->info0);
|
||||
+ 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.
|
||||
@@ -1509,6 +1522,12 @@ ath11k_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;
|
||||
+ peer_stats->ru_tones = ru_tone;
|
||||
+ peer_stats->ru_start = ru_start;
|
||||
+ peer_stats->mu_grpid = mu_grpid;
|
||||
+ peer_stats->mu_pos = mu_pos;
|
||||
+ peer_stats->ru_tones = arsta->txrate.he_ru_alloc;
|
||||
|
||||
if (ath11k_debugfs_is_extd_tx_stats_enabled(ar))
|
||||
ath11k_debugfs_sta_add_tx_stats(arsta, peer_stats, rate_idx);
|
||||
@@ -1561,13 +1580,89 @@ struct htt_ppdu_stats_info *ath11k_dp_ht
|
||||
return ppdu_info;
|
||||
}
|
||||
|
||||
+void ath11k_copy_to_delay_stats(struct ath11k_peer *peer,
|
||||
+ struct htt_ppdu_user_stats* usr_stats)
|
||||
+{
|
||||
+ peer->ppdu_stats_delayba.reserved0 = usr_stats->rate.reserved0;
|
||||
+ peer->ppdu_stats_delayba.sw_peer_id = usr_stats->rate.sw_peer_id;
|
||||
+ peer->ppdu_stats_delayba.info0 = usr_stats->rate.info0;
|
||||
+ peer->ppdu_stats_delayba.ru_end = usr_stats->rate.ru_end;
|
||||
+ peer->ppdu_stats_delayba.ru_start = usr_stats->rate.ru_start;
|
||||
+ peer->ppdu_stats_delayba.info1 = usr_stats->rate.info1;
|
||||
+ peer->ppdu_stats_delayba.rate_flags = usr_stats->rate.rate_flags;
|
||||
+ peer->ppdu_stats_delayba.resp_rate_flags = usr_stats->rate.resp_rate_flags;
|
||||
+
|
||||
+ peer->delayba_flag = true;
|
||||
+}
|
||||
+
|
||||
+void ath11k_copy_to_bar(struct ath11k_peer *peer,
|
||||
+ struct htt_ppdu_user_stats* usr_stats)
|
||||
+{
|
||||
+ usr_stats->rate.reserved0 = peer->ppdu_stats_delayba.reserved0;
|
||||
+ usr_stats->rate.sw_peer_id = peer->ppdu_stats_delayba.sw_peer_id;
|
||||
+ usr_stats->rate.info0 = peer->ppdu_stats_delayba.info0;
|
||||
+ usr_stats->rate.ru_end = peer->ppdu_stats_delayba.ru_end;
|
||||
+ usr_stats->rate.ru_start = peer->ppdu_stats_delayba.ru_start;
|
||||
+ usr_stats->rate.info1 = peer->ppdu_stats_delayba.info1;
|
||||
+ usr_stats->rate.rate_flags = peer->ppdu_stats_delayba.rate_flags;
|
||||
+ usr_stats->rate.resp_rate_flags = peer->ppdu_stats_delayba.resp_rate_flags;
|
||||
+
|
||||
+ peer->delayba_flag = false;
|
||||
+}
|
||||
+
|
||||
+int ath11k_dp_htt_tlv_iter(struct ath11k_base *ab, const void *ptr, size_t len,
|
||||
+ int (*iter)(struct ath11k_base *ar, u16 tag, u16 len,
|
||||
+ const void *ptr, void *data),
|
||||
+ void *data)
|
||||
+{
|
||||
+ const struct htt_tlv *tlv;
|
||||
+ const void *begin = ptr;
|
||||
+ u16 tlv_tag, tlv_len;
|
||||
+ int ret = -EINVAL;
|
||||
+ struct htt_ppdu_stats_info * ppdu_info = NULL;
|
||||
+
|
||||
+ if (data) {
|
||||
+ ppdu_info = (struct htt_ppdu_stats_info *)data;
|
||||
+ ppdu_info->tlv_bitmap = 0;
|
||||
+ }
|
||||
+ while (len > 0) {
|
||||
+ if (len < sizeof(*tlv)) {
|
||||
+ ath11k_err(ab, "htt tlv parse failure at byte %zd (%zu bytes left, %zu expected)\n",
|
||||
+ ptr - begin, len, sizeof(*tlv));
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ tlv = (struct htt_tlv *)ptr;
|
||||
+ tlv_tag = FIELD_GET(HTT_TLV_TAG, tlv->header);
|
||||
+ tlv_len = FIELD_GET(HTT_TLV_LEN, tlv->header);
|
||||
+ ptr += sizeof(*tlv);
|
||||
+ len -= sizeof(*tlv);
|
||||
+
|
||||
+ if (tlv_len > len) {
|
||||
+ ath11k_err(ab, "htt tlv parse failure of tag %hhu at byte %zd (%zu bytes left, %hhu expected)\n",
|
||||
+ tlv_tag, ptr - begin, len, tlv_len);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ ret = iter(ab, tlv_tag, tlv_len, ptr, ppdu_info);
|
||||
+ if (ret == -ENOMEM)
|
||||
+ return ret;
|
||||
+
|
||||
+ ptr += tlv_len;
|
||||
+ len -= tlv_len;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int ath11k_htt_pull_ppdu_stats(struct ath11k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ath11k_htt_ppdu_stats_msg *msg;
|
||||
struct htt_ppdu_stats_info *ppdu_info;
|
||||
+ struct ath11k_peer *peer = NULL;
|
||||
+ struct htt_ppdu_user_stats* usr_stats = NULL;
|
||||
+ u32 peer_id = 0;
|
||||
struct ath11k *ar;
|
||||
- int ret;
|
||||
+ int ret, i;
|
||||
u8 pdev_id;
|
||||
u32 ppdu_id, len;
|
||||
|
||||
@@ -1602,6 +1697,47 @@ static int ath11k_htt_pull_ppdu_stats(st
|
||||
goto out_unlock_data;
|
||||
}
|
||||
|
||||
+ /* back up data rate tlv for all peers */
|
||||
+ if (ppdu_info->frame_type == HTT_STATS_PPDU_FTYPE_DATA &&
|
||||
+ (ppdu_info->tlv_bitmap & (1 << HTT_PPDU_STATS_TAG_USR_COMMON)) &&
|
||||
+ ppdu_info->delay_ba) {
|
||||
+
|
||||
+ for (i = 0; i < ppdu_info->ppdu_stats.common.num_users; i++) {
|
||||
+ peer_id = ppdu_info->ppdu_stats.user_stats[i].peer_id;
|
||||
+ spin_lock_bh(&ab->base_lock);
|
||||
+ peer = ath11k_peer_find_by_id(ab, peer_id);
|
||||
+ if (!peer) {
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ usr_stats = &ppdu_info->ppdu_stats.user_stats[i];
|
||||
+ if (usr_stats->delay_ba)
|
||||
+ ath11k_copy_to_delay_stats(peer, usr_stats);
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* restore all peers' data rate tlv to mu-bar tlv */
|
||||
+ if (ppdu_info->frame_type == HTT_STATS_PPDU_FTYPE_BAR &&
|
||||
+ (ppdu_info->tlv_bitmap & (1 << HTT_PPDU_STATS_TAG_USR_COMMON))) {
|
||||
+
|
||||
+ for (i = 0; i < ppdu_info->bar_num_users; i++) {
|
||||
+ peer_id = ppdu_info->ppdu_stats.user_stats[i].peer_id;
|
||||
+ spin_lock_bh(&ab->base_lock);
|
||||
+ peer = ath11k_peer_find_by_id(ab, peer_id);
|
||||
+ if (!peer) {
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ usr_stats = &ppdu_info->ppdu_stats.user_stats[i];
|
||||
+ if (peer->delayba_flag)
|
||||
+ ath11k_copy_to_bar(peer, usr_stats);
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
out_unlock_data:
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/rx_desc.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/rx_desc.h
|
||||
@@ -1495,6 +1495,11 @@ struct hal_rx_desc {
|
||||
} u;
|
||||
} __packed;
|
||||
|
||||
+#define MAX_USER_POS 8
|
||||
+#define MAX_MU_GROUP_ID 64
|
||||
+#define MAX_MU_GROUP_SHOW 16
|
||||
+#define MAX_MU_GROUP_LENGTH (6 * MAX_MU_GROUP_SHOW)
|
||||
+
|
||||
#define HAL_RX_RU_ALLOC_TYPE_MAX 6
|
||||
#define RU_26 1
|
||||
#define RU_52 2
|
||||
--- a/drivers/net/wireless/ath/ath11k/peer.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/peer.h
|
||||
@@ -7,6 +7,17 @@
|
||||
#ifndef ATH11K_PEER_H
|
||||
#define ATH11K_PEER_H
|
||||
|
||||
+struct ppdu_user_delayba {
|
||||
+ u8 reserved0;
|
||||
+ u16 sw_peer_id;
|
||||
+ u32 info0;
|
||||
+ u16 ru_end;
|
||||
+ u16 ru_start;
|
||||
+ u32 info1;
|
||||
+ u32 rate_flags;
|
||||
+ u32 resp_rate_flags;
|
||||
+};
|
||||
+
|
||||
struct ath11k_peer {
|
||||
struct list_head list;
|
||||
struct ieee80211_sta *sta;
|
||||
@@ -36,6 +47,8 @@ struct ath11k_peer {
|
||||
u16 sec_type_grp;
|
||||
bool is_authorized;
|
||||
bool dp_setup_done;
|
||||
+ struct ppdu_user_delayba ppdu_stats_delayba;
|
||||
+ bool delayba_flag;
|
||||
};
|
||||
|
||||
void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id);
|
||||
@ -0,0 +1,15 @@
|
||||
--- a/drivers/net/wireless/ath/ath11k/core.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/core.c
|
||||
@@ -28,10 +28,10 @@ module_param_named(crypto_mode, ath11k_c
|
||||
MODULE_PARM_DESC(crypto_mode, "crypto mode: 0-hardware, 1-software");
|
||||
|
||||
/* frame mode values are mapped as per enum ath11k_hw_txrx_mode */
|
||||
-unsigned int ath11k_frame_mode = ATH11K_HW_TXRX_NATIVE_WIFI;
|
||||
+unsigned int ath11k_frame_mode = ATH11K_HW_TXRX_ETHERNET;
|
||||
module_param_named(frame_mode, ath11k_frame_mode, uint, 0644);
|
||||
MODULE_PARM_DESC(frame_mode,
|
||||
- "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");
|
||||
+ "Datapath frame mode (0: raw, 1: native wifi, 2: ethernet(default))");
|
||||
|
||||
bool ath11k_ftm_mode;
|
||||
module_param_named(ftm_mode, ath11k_ftm_mode, bool, 0444);
|
||||
@ -0,0 +1,82 @@
|
||||
From 3827a38706dcf081992fccf30957b29e81a25e5c Mon Sep 17 00:00:00 2001
|
||||
From: Miles Hu <milehu@codeaurora.org>
|
||||
Date: Mon, 25 Nov 2019 10:24:41 -0800
|
||||
Subject: [PATCH] ath11k: fix ul-ofdma counter always zero in peer stats
|
||||
|
||||
The problem is caused by RSSI_LEGACY tlv is not handled properly.
|
||||
All ul mu receiption information need to be extracted from the tlv.
|
||||
|
||||
Signed-off-by: Miles Hu <milehu@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/debugfs_sta.c | 7 -------
|
||||
drivers/net/wireless/ath/ath11k/hal_rx.c | 17 +++++++++++++++++
|
||||
drivers/net/wireless/ath/ath11k/hal_rx.h | 8 ++++++++
|
||||
3 files changed, 25 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/debugfs_sta.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/debugfs_sta.c
|
||||
@@ -526,13 +526,6 @@ static ssize_t ath11k_dbg_sta_dump_rx_st
|
||||
rx_stats->byte_stats.rx_rate[i],
|
||||
(i + 1) % (he_rates_avail ? 12 : 8) ? "\t" : "\n");
|
||||
|
||||
- len += scnprintf(buf + len, size - len,
|
||||
- "\nDCM: %llu\nRU: 26 %llu 52: %llu 106: %llu 242: %llu 484: %llu 996: %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);
|
||||
--- a/drivers/net/wireless/ath/ath11k/hal_rx.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/hal_rx.c
|
||||
@@ -1479,6 +1479,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;
|
||||
+ u32 reception_type = 0;
|
||||
|
||||
/* TODO: Please note that the combined rssi will not be accurate
|
||||
* in MU case. Rssi in MU needs to be retrieved from
|
||||
@@ -1488,6 +1489,22 @@ ath11k_hal_rx_parse_mon_status_tlv(struc
|
||||
FIELD_GET(HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RSSI_COMB,
|
||||
__le32_to_cpu(rssi->info0));
|
||||
|
||||
+ reception_type =
|
||||
+ FIELD_GET(HAL_RX_PHYRX_RSSI_LEGACY_INFO_RSVD1_RECEPTION,
|
||||
+ __le32_to_cpu(rssi->rsvd[0]));
|
||||
+
|
||||
+ switch (reception_type) {
|
||||
+ case HAL_RECEPTION_TYPE_ULOFMDA:
|
||||
+ ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_OFDMA;
|
||||
+ break;
|
||||
+ case HAL_RECEPTION_TYPE_ULMIMO:
|
||||
+ ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_MU_MIMO;
|
||||
+ break;
|
||||
+ default:
|
||||
+ ppdu_info->reception_type = HAL_RX_RECEPTION_TYPE_SU;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
if (db2dbm) {
|
||||
for (i = 0; i < ARRAY_SIZE(rssi->preamble); i++) {
|
||||
ppdu_info->rssi_chain_pri20[i] =
|
||||
--- a/drivers/net/wireless/ath/ath11k/hal_rx.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/hal_rx.h
|
||||
@@ -415,6 +415,15 @@ struct hal_rx_he_sig_b2_ofdma_info {
|
||||
|
||||
#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO0_RSSI_COMB GENMASK(15, 8)
|
||||
|
||||
+#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_RSVD1_RECEPTION GENMASK(3, 0)
|
||||
+
|
||||
+enum hal_rx_ul_reception_type {
|
||||
+ HAL_RECEPTION_TYPE_ULOFMDA,
|
||||
+ HAL_RECEPTION_TYPE_ULMIMO,
|
||||
+ HAL_RECEPTION_TYPE_OTHER,
|
||||
+ HAL_RECEPTION_TYPE_FRAMELESS
|
||||
+};
|
||||
+
|
||||
#define HAL_RX_PHYRX_RSSI_PREAMBLE_PRI20 GENMASK(7, 0)
|
||||
|
||||
struct hal_rx_phyrx_chain_rssi {
|
||||
@ -0,0 +1,51 @@
|
||||
drivers/net/wireless/ath/ath11k/dp_rx.c | 3 ++-
|
||||
drivers/net/wireless/ath/ath11k/hal_rx.c | 3 +++
|
||||
drivers/net/wireless/ath/ath11k/hal_rx.h | 2 ++
|
||||
3 files changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
|
||||
@@ -5518,8 +5518,11 @@ int ath11k_dp_rx_process_mon_status(stru
|
||||
goto next_skb;
|
||||
}
|
||||
|
||||
- arsta = ath11k_sta_to_arsta(peer->sta);
|
||||
- ath11k_dp_rx_update_peer_stats(arsta, ppdu_info);
|
||||
+ if ((ppdu_info->fc_valid) &&
|
||||
+ (ppdu_info->ast_index != HAL_AST_IDX_INVALID)) {
|
||||
+ arsta = (struct ath11k_sta *)peer->sta->drv_priv;
|
||||
+ ath11k_dp_rx_update_peer_stats(arsta, ppdu_info);
|
||||
+ }
|
||||
|
||||
if (ath11k_debugfs_is_pktlog_peer_valid(ar, peer->addr))
|
||||
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
|
||||
@@ -901,6 +901,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));
|
||||
+ ppdu_info->fc_valid =
|
||||
+ FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO1_FC_VALID,
|
||||
+ __le32_to_cpu(eu_stats->info1));
|
||||
ppdu_info->tid =
|
||||
ffs(FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO7_TID_BITMAP,
|
||||
__le32_to_cpu(eu_stats->info7))) - 1;
|
||||
--- a/drivers/net/wireless/ath/ath11k/hal_rx.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/hal_rx.h
|
||||
@@ -71,6 +71,7 @@ enum hal_rx_reception_type {
|
||||
};
|
||||
|
||||
#define HAL_RX_FCS_LEN 4
|
||||
+#define HAL_AST_IDX_INVALID 0xFFFF
|
||||
|
||||
enum hal_rx_mon_status {
|
||||
HAL_RX_MON_STATUS_PPDU_NOT_DONE,
|
||||
@@ -172,6 +173,7 @@ struct hal_rx_mon_ppdu_info {
|
||||
u8 rssi_comb;
|
||||
u8 rssi_chain_pri20[HAL_RX_MAX_NSS];
|
||||
u16 tid;
|
||||
+ u8 fc_valid;
|
||||
u16 ht_flags;
|
||||
u16 vht_flags;
|
||||
u16 he_flags;
|
||||
@ -0,0 +1,452 @@
|
||||
--- a/drivers/net/wireless/ath/ath11k/debugfs_sta.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/debugfs_sta.c
|
||||
@@ -525,6 +525,12 @@ static ssize_t ath11k_dbg_sta_dump_rx_st
|
||||
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");
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
|
||||
@@ -2901,11 +2901,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,
|
||||
+ struct hal_rx_user_status* user_stats,
|
||||
u32 num_msdu)
|
||||
{
|
||||
u32 rate_idx = 0;
|
||||
- u32 mcs_idx = ppdu_info->mcs;
|
||||
- u32 nss_idx = ppdu_info->nss - 1;
|
||||
+ 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;
|
||||
u32 gi_idx = ppdu_info->gi;
|
||||
|
||||
@@ -2927,10 +2928,13 @@ ath11k_dp_rx_update_peer_rate_table_stat
|
||||
}
|
||||
|
||||
rx_stats->pkt_stats.rx_rate[rate_idx] += num_msdu;
|
||||
- rx_stats->byte_stats.rx_rate[rate_idx] += ppdu_info->mpdu_len;
|
||||
+ if (user_stats)
|
||||
+ rx_stats->byte_stats.rx_rate[rate_idx] += user_stats->mpdu_ok_byte_count;
|
||||
+ else
|
||||
+ rx_stats->byte_stats.rx_rate[rate_idx] += ppdu_info->mpdu_len;
|
||||
}
|
||||
|
||||
-static void ath11k_dp_rx_update_peer_stats(struct ath11k_sta *arsta,
|
||||
+static void ath11k_dp_rx_update_peer_su_stats(struct ath11k_sta *arsta,
|
||||
struct hal_rx_mon_ppdu_info *ppdu_info)
|
||||
{
|
||||
struct ath11k_rx_peer_stats *rx_stats = arsta->rx_stats;
|
||||
@@ -2988,7 +2992,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;
|
||||
- rx_stats->ru_alloc_cnt[ppdu_info->ru_alloc] += num_msdu;
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(arsta->chain_signal) >
|
||||
ARRAY_SIZE(ppdu_info->rssi_chain_pri20));
|
||||
@@ -3006,10 +3009,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) {
|
||||
- rx_stats->pkt_stats.ht_mcs_count[ppdu_info->mcs] += num_msdu;
|
||||
- rx_stats->byte_stats.ht_mcs_count[ppdu_info->mcs] += ppdu_info->mpdu_len;
|
||||
- /* To fit into rate table for HT packets */
|
||||
- ppdu_info->mcs = ppdu_info->mcs % 8;
|
||||
+ rx_stats->pkt_stats.ht_mcs_count[ppdu_info->mcs] += num_msdu;
|
||||
+ rx_stats->byte_stats.ht_mcs_count[ppdu_info->mcs] += ppdu_info->mpdu_len;
|
||||
+ /* To fit into rate table for HT packets */
|
||||
+ ppdu_info->mcs = ppdu_info->mcs % 8;
|
||||
}
|
||||
|
||||
if (ppdu_info->preamble_type == HAL_RX_PREAMBLE_11AC &&
|
||||
@@ -3042,7 +3045,120 @@ static void ath11k_dp_rx_update_peer_sta
|
||||
rx_stats->byte_stats.bw_count[ppdu_info->bw] += ppdu_info->mpdu_len;
|
||||
}
|
||||
|
||||
- ath11k_dp_rx_update_peer_rate_table_stats(rx_stats, ppdu_info, num_msdu);
|
||||
+ ath11k_dp_rx_update_peer_rate_table_stats(rx_stats, ppdu_info, NULL, num_msdu);
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static void ath11k_dp_rx_update_user_stats(struct ath11k *ar,
|
||||
+ struct hal_rx_mon_ppdu_info *ppdu_info,
|
||||
+ u32 uid)
|
||||
+{
|
||||
+ struct ath11k_sta *arsta = NULL;
|
||||
+ struct ath11k_rx_peer_stats *rx_stats = NULL;
|
||||
+ struct hal_rx_user_status* user_stats = &ppdu_info->userstats[uid];
|
||||
+ struct ath11k_peer *peer;
|
||||
+ u32 num_msdu;
|
||||
+
|
||||
+ if (user_stats->ast_index == 0 || user_stats->ast_index == 0xFFFF)
|
||||
+ return;
|
||||
+
|
||||
+ peer = ath11k_peer_find_by_ast(ar->ab, user_stats->ast_index);
|
||||
+
|
||||
+ if (peer == NULL) {
|
||||
+ ath11k_warn(ar->ab, "peer ast idx %d can't be found\n",
|
||||
+ user_stats->ast_index);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ arsta = (struct ath11k_sta *)peer->sta->drv_priv;
|
||||
+ rx_stats = arsta->rx_stats;
|
||||
+
|
||||
+ if (!rx_stats)
|
||||
+ return;
|
||||
+
|
||||
+ arsta->rssi_comb = ppdu_info->rssi_comb;
|
||||
+
|
||||
+ num_msdu = user_stats->tcp_msdu_count + user_stats->tcp_ack_msdu_count +
|
||||
+ user_stats->udp_msdu_count + user_stats->other_msdu_count;
|
||||
+
|
||||
+ rx_stats->num_msdu += num_msdu;
|
||||
+ rx_stats->tcp_msdu_count += user_stats->tcp_msdu_count +
|
||||
+ user_stats->tcp_ack_msdu_count;
|
||||
+ rx_stats->udp_msdu_count += user_stats->udp_msdu_count;
|
||||
+ rx_stats->other_msdu_count += user_stats->other_msdu_count;
|
||||
+
|
||||
+ if (ppdu_info->ldpc < HAL_RX_SU_MU_CODING_MAX)
|
||||
+ rx_stats->coding_count[ppdu_info->ldpc] += num_msdu;
|
||||
+
|
||||
+ if (user_stats->tid <= IEEE80211_NUM_TIDS)
|
||||
+ rx_stats->tid_count[user_stats->tid] += num_msdu;
|
||||
+
|
||||
+ if (user_stats->preamble_type < HAL_RX_PREAMBLE_MAX)
|
||||
+ rx_stats->pream_cnt[user_stats->preamble_type] += num_msdu;
|
||||
+
|
||||
+ if (ppdu_info->reception_type < HAL_RX_RECEPTION_TYPE_MAX)
|
||||
+ rx_stats->reception_type[ppdu_info->reception_type] += num_msdu;
|
||||
+
|
||||
+ if (ppdu_info->is_stbc)
|
||||
+ rx_stats->stbc_count += num_msdu;
|
||||
+
|
||||
+ if (ppdu_info->beamformed)
|
||||
+ rx_stats->beamformed_count += num_msdu;
|
||||
+
|
||||
+ if (user_stats->mpdu_cnt_fcs_ok > 1)
|
||||
+ rx_stats->ampdu_msdu_count += num_msdu;
|
||||
+ else
|
||||
+ rx_stats->non_ampdu_msdu_count += num_msdu;
|
||||
+
|
||||
+ rx_stats->num_mpdu_fcs_ok += user_stats->mpdu_cnt_fcs_ok;
|
||||
+ rx_stats->num_mpdu_fcs_err += user_stats->mpdu_cnt_fcs_err;
|
||||
+ rx_stats->dcm_count += ppdu_info->dcm;
|
||||
+ if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_MU_OFDMA ||
|
||||
+ ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_MU_OFDMA_MIMO)
|
||||
+ rx_stats->ru_alloc_cnt[user_stats->ul_ofdma_ru_size] += num_msdu;
|
||||
+
|
||||
+ rx_stats->rx_duration += ppdu_info->rx_duration;
|
||||
+ arsta->rx_duration = rx_stats->rx_duration;
|
||||
+
|
||||
+ if (user_stats->nss > 0 && user_stats->nss <= HAL_RX_MAX_NSS) {
|
||||
+ rx_stats->pkt_stats.nss_count[user_stats->nss - 1] += num_msdu;
|
||||
+ rx_stats->byte_stats.nss_count[user_stats->nss - 1] += user_stats->mpdu_ok_byte_count;
|
||||
+ }
|
||||
+
|
||||
+ if (user_stats->preamble_type == HAL_RX_PREAMBLE_11AX &&
|
||||
+ user_stats->mcs <= HAL_RX_MAX_MCS_HE) {
|
||||
+ rx_stats->pkt_stats.he_mcs_count[user_stats->mcs] += num_msdu;
|
||||
+ rx_stats->byte_stats.he_mcs_count[user_stats->mcs] += user_stats->mpdu_ok_byte_count;
|
||||
+ }
|
||||
+
|
||||
+ if (ppdu_info->gi < HAL_RX_GI_MAX) {
|
||||
+ rx_stats->pkt_stats.gi_count[ppdu_info->gi] += num_msdu;
|
||||
+ rx_stats->byte_stats.gi_count[ppdu_info->gi] += user_stats->mpdu_ok_byte_count;
|
||||
+ }
|
||||
+
|
||||
+ if (ppdu_info->bw < HAL_RX_BW_MAX) {
|
||||
+ rx_stats->pkt_stats.bw_count[ppdu_info->bw] += num_msdu;
|
||||
+ rx_stats->byte_stats.bw_count[ppdu_info->bw] += user_stats->mpdu_ok_byte_count;
|
||||
+ }
|
||||
+
|
||||
+ ath11k_dp_rx_update_peer_rate_table_stats(rx_stats, ppdu_info, user_stats, num_msdu);
|
||||
+}
|
||||
+
|
||||
+static void ath11k_dp_rx_update_peer_mu_stats(struct ath11k *ar,
|
||||
+ struct hal_rx_mon_ppdu_info *ppdu_info)
|
||||
+{
|
||||
+ u32 num_users, i;
|
||||
+
|
||||
+ if (!ath11k_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;
|
||||
+
|
||||
+ for (i = 0; i < num_users; i++) {
|
||||
+ ath11k_dp_rx_update_user_stats(ar, ppdu_info, i);
|
||||
+ }
|
||||
|
||||
}
|
||||
|
||||
@@ -5444,6 +5560,55 @@ static void ath11k_dp_rx_mon_dest_proces
|
||||
}
|
||||
}
|
||||
|
||||
+void ath11k_dp_rx_mon_process_ulofdma(struct hal_rx_mon_ppdu_info *ppdu_info)
|
||||
+{
|
||||
+ struct hal_rx_user_status *rx_user_status;
|
||||
+ u32 num_users;
|
||||
+ uint32_t i;
|
||||
+ uint32_t mu_ul_user_v0_word0;
|
||||
+ uint32_t mu_ul_user_v0_word1;
|
||||
+ uint32_t ru_size;
|
||||
+
|
||||
+ if (!(ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_MU_OFDMA ||
|
||||
+ ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_MU_OFDMA_MIMO))
|
||||
+ return;
|
||||
+
|
||||
+ num_users = ppdu_info->num_users;
|
||||
+ if (num_users > HAL_MAX_UL_MU_USERS)
|
||||
+ num_users = HAL_MAX_UL_MU_USERS;
|
||||
+
|
||||
+ for (i = 0; i < num_users; i++) {
|
||||
+ rx_user_status = &ppdu_info->userstats[i];
|
||||
+ mu_ul_user_v0_word0 =
|
||||
+ rx_user_status->ul_ofdma_user_v0_word0;
|
||||
+ mu_ul_user_v0_word1 =
|
||||
+ rx_user_status->ul_ofdma_user_v0_word1;
|
||||
+
|
||||
+ if (FIELD_GET(HAL_RX_UL_OFDMA_USER_INFO_V0_W0_VALID,
|
||||
+ mu_ul_user_v0_word0) &&
|
||||
+ !FIELD_GET(HAL_RX_UL_OFDMA_USER_INFO_V0_W0_VER,
|
||||
+ mu_ul_user_v0_word0)) {
|
||||
+ rx_user_status->mcs =
|
||||
+ FIELD_GET(HAL_RX_UL_OFDMA_USER_INFO_V0_W1_MCS,
|
||||
+ mu_ul_user_v0_word1);
|
||||
+ rx_user_status->nss =
|
||||
+ FIELD_GET(HAL_RX_UL_OFDMA_USER_INFO_V0_W1_NSS,
|
||||
+ mu_ul_user_v0_word1) + 1;
|
||||
+
|
||||
+ rx_user_status->ofdma_info_valid = 1;
|
||||
+ rx_user_status->ul_ofdma_ru_start_index =
|
||||
+ FIELD_GET(HAL_RX_UL_OFDMA_USER_INFO_V0_W1_RU_START,
|
||||
+ mu_ul_user_v0_word1);
|
||||
+
|
||||
+ ru_size = FIELD_GET(HAL_RX_UL_OFDMA_USER_INFO_V0_W1_RU_SIZE,
|
||||
+ mu_ul_user_v0_word1);
|
||||
+ rx_user_status->ul_ofdma_ru_width = ru_size;
|
||||
+ rx_user_status->ul_ofdma_ru_size = ru_size;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
+
|
||||
int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
|
||||
struct napi_struct *napi, int budget)
|
||||
{
|
||||
@@ -5520,8 +5685,13 @@ int ath11k_dp_rx_process_mon_status(stru
|
||||
|
||||
if ((ppdu_info->fc_valid) &&
|
||||
(ppdu_info->ast_index != HAL_AST_IDX_INVALID)) {
|
||||
- arsta = (struct ath11k_sta *)peer->sta->drv_priv;
|
||||
- ath11k_dp_rx_update_peer_stats(arsta, ppdu_info);
|
||||
+ 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);
|
||||
+ } else {
|
||||
+ ath11k_dp_rx_mon_process_ulofdma(ppdu_info);
|
||||
+ ath11k_dp_rx_update_peer_mu_stats(ar, ppdu_info);
|
||||
+ }
|
||||
}
|
||||
|
||||
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
|
||||
@@ -805,7 +805,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)
|
||||
@@ -837,6 +836,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;
|
||||
+ rx_user_status->tcp_ack_msdu_count =
|
||||
+ ppdu_info->tcp_ack_msdu_count;
|
||||
rx_user_status->tcp_msdu_count =
|
||||
ppdu_info->tcp_msdu_count;
|
||||
rx_user_status->udp_msdu_count =
|
||||
@@ -860,6 +861,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;
|
||||
+ memcpy(&rx_user_status->mpdu_fcs_ok_bitmap[0], &ppdu_info->mpdu_fcs_ok_bitmap[0],
|
||||
+ HAL_RX_NUM_WORDS_PER_PPDU_BITMAP *
|
||||
+ sizeof(ppdu_info->mpdu_fcs_ok_bitmap[0]));
|
||||
|
||||
ath11k_hal_rx_populate_byte_count(rx_tlv, ppdu_info, rx_user_status);
|
||||
}
|
||||
@@ -889,6 +893,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);
|
||||
+
|
||||
+ if (ppdu_info->ppdu_id != ppdu_info->last_ppdu_id) {
|
||||
+ ppdu_info->last_ppdu_id = ppdu_info->ppdu_id;
|
||||
+ ppdu_info->num_users = 0;
|
||||
+ memset(&ppdu_info->mpdu_fcs_ok_bitmap, 0,
|
||||
+ HAL_RX_NUM_WORDS_PER_PPDU_BITMAP *
|
||||
+ sizeof(ppdu_info->mpdu_fcs_ok_bitmap[0]));
|
||||
+ }
|
||||
break;
|
||||
}
|
||||
case HAL_RX_PPDU_END_USER_STATS: {
|
||||
@@ -943,15 +955,16 @@ ath11k_hal_rx_parse_mon_status_tlv(struc
|
||||
|
||||
if (userid < HAL_MAX_UL_MU_USERS) {
|
||||
struct hal_rx_user_status *rxuser_stats =
|
||||
- &ppdu_info->userstats;
|
||||
+ &ppdu_info->userstats[userid];
|
||||
+ ppdu_info->num_users += 1;
|
||||
|
||||
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] =
|
||||
+ 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;
|
||||
@@ -959,12 +972,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;
|
||||
- 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;
|
||||
+ ppdu_info->mpdu_fcs_ok_bitmap[2] = eu_stats->info1;
|
||||
+ ppdu_info->mpdu_fcs_ok_bitmap[3] = eu_stats->info2;
|
||||
+ ppdu_info->mpdu_fcs_ok_bitmap[4] = eu_stats->info3;
|
||||
+ ppdu_info->mpdu_fcs_ok_bitmap[5] = eu_stats->info4;
|
||||
+ ppdu_info->mpdu_fcs_ok_bitmap[6] = eu_stats->info5;
|
||||
+ ppdu_info->mpdu_fcs_ok_bitmap[7] = eu_stats->info6;
|
||||
break;
|
||||
}
|
||||
case HAL_PHYRX_HT_SIG: {
|
||||
--- a/drivers/net/wireless/ath/ath11k/hal_rx.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/hal_rx.h
|
||||
@@ -73,6 +73,10 @@ enum hal_rx_reception_type {
|
||||
#define HAL_RX_FCS_LEN 4
|
||||
#define HAL_AST_IDX_INVALID 0xFFFF
|
||||
|
||||
+#define HAL_MAX_UL_MU_USERS 37
|
||||
+#define HAL_RX_MAX_MPDU 256
|
||||
+#define HAL_RX_NUM_WORDS_PER_PPDU_BITMAP (HAL_RX_MAX_MPDU >> 5)
|
||||
+
|
||||
enum hal_rx_mon_status {
|
||||
HAL_RX_MON_STATUS_PPDU_NOT_DONE,
|
||||
HAL_RX_MON_STATUS_PPDU_DONE,
|
||||
@@ -83,14 +87,15 @@ 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;
|
||||
+ ul_ofdma_ru_start_index:7,
|
||||
+ ul_ofdma_ru_width:7,
|
||||
+ ul_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 tcp_ack_msdu_count;
|
||||
u16 udp_msdu_count;
|
||||
u16 other_msdu_count;
|
||||
u16 frame_control;
|
||||
@@ -104,7 +109,7 @@ struct hal_rx_user_status {
|
||||
u8 rs_flags;
|
||||
u32 mpdu_cnt_fcs_ok;
|
||||
u32 mpdu_cnt_fcs_err;
|
||||
- u32 mpdu_fcs_ok_bitmap[8];
|
||||
+ u32 mpdu_fcs_ok_bitmap[HAL_RX_NUM_WORDS_PER_PPDU_BITMAP];
|
||||
u32 mpdu_ok_byte_count;
|
||||
u32 mpdu_err_byte_count;
|
||||
};
|
||||
@@ -145,6 +150,7 @@ struct hal_sw_mon_ring_entries {
|
||||
|
||||
struct hal_rx_mon_ppdu_info {
|
||||
u32 ppdu_id;
|
||||
+ u32 last_ppdu_id;
|
||||
u32 ppdu_ts;
|
||||
u32 num_mpdu_fcs_ok;
|
||||
u32 num_mpdu_fcs_err;
|
||||
@@ -213,9 +219,20 @@ struct hal_rx_mon_ppdu_info {
|
||||
u8 ltf_size;
|
||||
u8 rxpcu_filter_pass;
|
||||
char rssi_chain[8][8];
|
||||
- struct hal_rx_user_status userstats;
|
||||
+ u32 num_users;
|
||||
+ u32 mpdu_fcs_ok_bitmap[HAL_RX_NUM_WORDS_PER_PPDU_BITMAP];
|
||||
+ struct hal_rx_user_status userstats[HAL_MAX_UL_MU_USERS];
|
||||
};
|
||||
|
||||
+#define HAL_RX_UL_OFDMA_USER_INFO_V0_W0_VALID BIT(30)
|
||||
+#define HAL_RX_UL_OFDMA_USER_INFO_V0_W0_VER BIT(31)
|
||||
+#define HAL_RX_UL_OFDMA_USER_INFO_V0_W1_NSS GENMASK(2, 0)
|
||||
+#define HAL_RX_UL_OFDMA_USER_INFO_V0_W1_MCS GENMASK(6, 3)
|
||||
+#define HAL_RX_UL_OFDMA_USER_INFO_V0_W1_LDPC BIT(7)
|
||||
+#define HAL_RX_UL_OFDMA_USER_INFO_V0_W1_DCM BIT(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)
|
||||
+
|
||||
#define HAL_RX_PPDU_START_INFO0_PPDU_ID GENMASK(15, 0)
|
||||
|
||||
struct hal_rx_ppdu_start {
|
||||
--- a/drivers/net/wireless/ath/ath11k/peer.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/peer.c
|
||||
@@ -93,6 +93,20 @@ struct ath11k_peer *ath11k_peer_find_by_
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+struct ath11k_peer *ath11k_peer_find_by_ast(struct ath11k_base *ab,
|
||||
+ int ast_hash)
|
||||
+{
|
||||
+ struct ath11k_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 ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id)
|
||||
{
|
||||
struct ath11k_peer *peer;
|
||||
--- a/drivers/net/wireless/ath/ath11k/peer.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/peer.h
|
||||
@@ -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);
|
||||
+struct ath11k_peer *ath11k_peer_find_by_ast(struct ath11k_base *ab, int ast_hash);
|
||||
void ath11k_peer_cleanup(struct ath11k *ar, u32 vdev_id);
|
||||
int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr);
|
||||
int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
@ -0,0 +1,55 @@
|
||||
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
|
||||
@@ -2305,6 +2305,42 @@ static void ath11k_dp_rx_h_undecap_eth(s
|
||||
ether_addr_copy(ieee80211_get_SA(hdr), sa);
|
||||
}
|
||||
|
||||
+static void ath11k_dp_rx_h_undecap_snap(struct ath11k *ar,
|
||||
+ struct sk_buff *msdu,
|
||||
+ u8 *first_hdr,
|
||||
+ enum hal_encrypt_type enctype,
|
||||
+ struct ieee80211_rx_status *status)
|
||||
+{
|
||||
+ struct ieee80211_hdr *hdr;
|
||||
+ size_t hdr_len;
|
||||
+ u8 l3_pad_bytes;
|
||||
+ struct hal_rx_desc *rx_desc;
|
||||
+
|
||||
+ /* Delivered decapped frame:
|
||||
+ * [amsdu header] <-- replaced with 802.11 hdr
|
||||
+ * [rfc1042/llc]
|
||||
+ * [payload]
|
||||
+ */
|
||||
+
|
||||
+ rx_desc = (void *)msdu->data - sizeof(*rx_desc);
|
||||
+ l3_pad_bytes = ath11k_dp_rx_h_msdu_end_l3pad(ar->ab, rx_desc);
|
||||
+
|
||||
+ skb_put(msdu, l3_pad_bytes);
|
||||
+ skb_pull(msdu, sizeof(struct ath11k_dp_amsdu_subframe_hdr) + l3_pad_bytes);
|
||||
+
|
||||
+ hdr = (struct ieee80211_hdr *)first_hdr;
|
||||
+ 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));
|
||||
+ }
|
||||
+
|
||||
+ memcpy(skb_push(msdu, hdr_len), hdr, hdr_len);
|
||||
+}
|
||||
+
|
||||
static void ath11k_dp_rx_h_undecap(struct ath11k *ar, struct sk_buff *msdu,
|
||||
struct hal_rx_desc *rx_desc,
|
||||
enum hal_encrypt_type enctype,
|
||||
@@ -2346,7 +2382,8 @@ static void ath11k_dp_rx_h_undecap(struc
|
||||
enctype, status);
|
||||
break;
|
||||
case DP_RX_DECAP_TYPE_8023:
|
||||
- /* TODO: Handle undecap for these formats */
|
||||
+ ath11k_dp_rx_h_undecap_snap(ar, msdu, first_hdr,
|
||||
+ enctype, status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,308 @@
|
||||
--- a/drivers/net/wireless/ath/ath11k/core.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <linux/average.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
+#include "fw.h"
|
||||
#include "qmi.h"
|
||||
#include "htc.h"
|
||||
#include "wmi.h"
|
||||
@@ -32,7 +33,6 @@
|
||||
#include "spectral.h"
|
||||
#include "wow.h"
|
||||
#include "rx_desc.h"
|
||||
-#include "fw.h"
|
||||
|
||||
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
|
||||
|
||||
@@ -362,6 +362,16 @@ struct ath11k_reg_tpc_power_info {
|
||||
struct ath11k_chan_power_info chan_power_info[ATH11K_NUM_PWR_LEVELS];
|
||||
};
|
||||
|
||||
+#define ATH11K_STATS_MGMT_FRM_TYPE_MAX 16
|
||||
+
|
||||
+struct ath11k_mgmt_frame_stats {
|
||||
+ u32 tx_succ_cnt[ATH11K_STATS_MGMT_FRM_TYPE_MAX];
|
||||
+ u32 tx_fail_cnt[ATH11K_STATS_MGMT_FRM_TYPE_MAX];
|
||||
+ u32 rx_cnt[ATH11K_STATS_MGMT_FRM_TYPE_MAX];
|
||||
+ u32 tx_compl_succ[ATH11K_STATS_MGMT_FRM_TYPE_MAX];
|
||||
+ u32 tx_compl_fail[ATH11K_STATS_MGMT_FRM_TYPE_MAX];
|
||||
+};
|
||||
+
|
||||
struct ath11k_vif {
|
||||
u32 vdev_id;
|
||||
enum wmi_vdev_type vdev_type;
|
||||
@@ -418,7 +428,7 @@ struct ath11k_vif {
|
||||
struct ath11k_rekey_data rekey_data;
|
||||
|
||||
struct ath11k_reg_tpc_power_info reg_tpc_info;
|
||||
-
|
||||
+ struct ath11k_mgmt_frame_stats mgmt_stats;
|
||||
/* Must be last - ends in a flexible-array member.
|
||||
*
|
||||
* FIXME: Driver should not copy struct ieee80211_chanctx_conf,
|
||||
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
|
||||
@@ -1589,6 +1589,87 @@ static const struct file_operations fops
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
+static ssize_t ath11k_dump_mgmt_stats(struct file *file, char __user *ubuf,
|
||||
+ size_t count, loff_t *ppos)
|
||||
+{
|
||||
+ struct ath11k *ar = file->private_data;
|
||||
+ struct ath11k_vif *arvif = NULL;
|
||||
+ struct ath11k_mgmt_frame_stats *mgmt_stats;
|
||||
+ int len = 0, ret, i;
|
||||
+ int size = (TARGET_NUM_VDEVS(ar->ab) - 1) * 1500;
|
||||
+ char *buf;
|
||||
+ const char *mgmt_frm_type[ATH11K_STATS_MGMT_FRM_TYPE_MAX-1] = {"assoc_req", "assoc_resp",
|
||||
+ "reassoc_req", "reassoc_resp",
|
||||
+ "probe_req", "probe_resp",
|
||||
+ "timing_advertisement", "reserved",
|
||||
+ "beacon", "atim", "disassoc",
|
||||
+ "auth", "deauth", "action", "action_no_ack"};
|
||||
+
|
||||
+ if (ar->state != ATH11K_STATE_ON)
|
||||
+ return -ENETDOWN;
|
||||
+
|
||||
+ buf = kzalloc(size, GFP_KERNEL);
|
||||
+ if (!buf)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ mutex_lock(&ar->conf_mutex);
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+
|
||||
+ list_for_each_entry (arvif, &ar->arvifs, list) {
|
||||
+ if (!arvif)
|
||||
+ break;
|
||||
+
|
||||
+ if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
|
||||
+ continue;
|
||||
+
|
||||
+ mgmt_stats = &arvif->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");
|
||||
+ for (i = 0; i < ATH11K_STATS_MGMT_FRM_TYPE_MAX-1; i++)
|
||||
+ len += scnprintf(buf + len, size - len, " %s: %d\n", mgmt_frm_type[i],
|
||||
+ mgmt_stats->tx_succ_cnt[i]);
|
||||
+
|
||||
+ len += scnprintf(buf + len, size - len, " Failed frames:\n");
|
||||
+
|
||||
+ for (i = 0; i < ATH11K_STATS_MGMT_FRM_TYPE_MAX-1; i++)
|
||||
+ len += scnprintf(buf + len, size - len, " %s: %d\n", mgmt_frm_type[i],
|
||||
+ mgmt_stats->tx_fail_cnt[i]);
|
||||
+
|
||||
+ len += scnprintf(buf + len, size - len, " RX stats :\n");
|
||||
+ len += scnprintf(buf + len, size - len, " Success frames:\n");
|
||||
+ for (i = 0; i < ATH11K_STATS_MGMT_FRM_TYPE_MAX-1; i++)
|
||||
+ len += scnprintf(buf + len, size - len, " %s: %d\n", mgmt_frm_type[i],
|
||||
+ mgmt_stats->rx_cnt[i]);
|
||||
+
|
||||
+ len += scnprintf(buf + len, size - len, " Tx completion stats :\n");
|
||||
+ len += scnprintf(buf + len, size - len, " success completions:\n");
|
||||
+ for (i = 0; i < ATH11K_STATS_MGMT_FRM_TYPE_MAX-1; i++)
|
||||
+ len += scnprintf(buf + len, size - len, " %s: %d\n", mgmt_frm_type[i],
|
||||
+ mgmt_stats->tx_compl_succ[i]);
|
||||
+ len += scnprintf(buf + len, size - len, " failure completions:\n");
|
||||
+ for (i = 0; i < ATH11K_STATS_MGMT_FRM_TYPE_MAX-1; i++)
|
||||
+ len += scnprintf(buf + len, size - len, " %s: %d\n", mgmt_frm_type[i],
|
||||
+ mgmt_stats->tx_compl_fail[i]);
|
||||
+ }
|
||||
+
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
+
|
||||
+ if (len > size)
|
||||
+ len = size;
|
||||
+
|
||||
+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, len);
|
||||
+ mutex_unlock(&ar->conf_mutex);
|
||||
+ kfree(buf);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static const struct file_operations fops_dump_mgmt_stats = {
|
||||
+ .read = ath11k_dump_mgmt_stats,
|
||||
+ .open = simple_open
|
||||
+};
|
||||
+
|
||||
int ath11k_debugfs_register(struct ath11k *ar)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
@@ -1621,6 +1702,9 @@ int ath11k_debugfs_register(struct ath11
|
||||
debugfs_create_file("fw_dbglog_config", 0600,
|
||||
ar->debug.debugfs_pdev, ar,
|
||||
&fops_fw_dbglog);
|
||||
+ debugfs_create_file("dump_mgmt_stats", 0644,
|
||||
+ ar->debug.debugfs_pdev, ar,
|
||||
+ &fops_dump_mgmt_stats);
|
||||
|
||||
if (ar->hw->wiphy->bands[NL80211_BAND_5GHZ]) {
|
||||
debugfs_create_file("dfs_simulate_radar", 0200,
|
||||
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
||||
@@ -6034,9 +6034,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) {
|
||||
- ath11k_warn(ar->ab,
|
||||
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
||||
"dropping probe response as pending queue is almost full\n");
|
||||
- return -ENOSPC;
|
||||
+ return -EBUSY;
|
||||
}
|
||||
|
||||
if (skb_queue_len_lockless(q) >= ATH11K_TX_MGMT_NUM_PENDING_MAX) {
|
||||
@@ -6062,9 +6062,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;
|
||||
+ struct ath11k_mgmt_frame_stats *mgmt_stats = &arvif->mgmt_stats;
|
||||
struct ath11k_sta *arsta = NULL;
|
||||
u32 info_flags = info->flags;
|
||||
bool is_prb_rsp;
|
||||
+ u16 frm_type = 0;
|
||||
int ret;
|
||||
|
||||
memset(skb_cb, 0, sizeof(*skb_cb));
|
||||
@@ -6078,12 +6080,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)) {
|
||||
+ frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, hdr->frame_control);
|
||||
is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control);
|
||||
ret = ath11k_mac_mgmt_tx(ar, skb, is_prb_rsp);
|
||||
if (ret) {
|
||||
- ath11k_warn(ar->ab, "failed to queue management frame %d\n",
|
||||
- ret);
|
||||
+ if (ret != -EBUSY)
|
||||
+ ath11k_warn(ar->ab, "failed to queue management frame %d\n",
|
||||
+ ret);
|
||||
ieee80211_free_txskb(ar->hw, skb);
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+ mgmt_stats->tx_fail_cnt[frm_type]++;
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
+ } else {
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+ mgmt_stats->tx_succ_cnt[frm_type]++;
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
return;
|
||||
}
|
||||
--- a/drivers/net/wireless/ath/ath11k/peer.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/peer.c
|
||||
@@ -458,6 +458,7 @@ int ath11k_peer_create(struct ath11k *ar
|
||||
|
||||
peer->sec_type = HAL_ENCRYPT_TYPE_OPEN;
|
||||
peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN;
|
||||
+ peer->vif = arvif->vif;
|
||||
|
||||
if (sta) {
|
||||
arsta = ath11k_sta_to_arsta(sta);
|
||||
--- a/drivers/net/wireless/ath/ath11k/peer.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/peer.h
|
||||
@@ -21,6 +21,7 @@ struct ppdu_user_delayba {
|
||||
struct ath11k_peer {
|
||||
struct list_head list;
|
||||
struct ieee80211_sta *sta;
|
||||
+ struct ieee80211_vif *vif;
|
||||
int vdev_id;
|
||||
u8 addr[ETH_ALEN];
|
||||
int peer_id;
|
||||
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
@@ -5943,6 +5943,12 @@ static int wmi_process_mgmt_tx_comp(stru
|
||||
struct sk_buff *msdu;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ath11k_skb_cb *skb_cb;
|
||||
+ struct ieee80211_hdr *hdr;
|
||||
+ struct ath11k_peer *peer;
|
||||
+ struct ieee80211_vif *vif;
|
||||
+ struct ath11k_vif *arvif;
|
||||
+ struct ath11k_mgmt_frame_stats *mgmt_stats;
|
||||
+ u16 frm_type;
|
||||
int num_mgmt;
|
||||
|
||||
spin_lock_bh(&ar->txmgmt_idr_lock);
|
||||
@@ -5970,6 +5976,31 @@ static int wmi_process_mgmt_tx_comp(stru
|
||||
info->status.ack_signal = tx_compl_param->ack_rssi;
|
||||
}
|
||||
|
||||
+ hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
+ frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, hdr->frame_control);
|
||||
+
|
||||
+ spin_lock_bh(&ar->ab->base_lock);
|
||||
+ peer = ath11k_peer_find_by_addr(ar->ab, hdr->addr2);
|
||||
+ if (!peer) {
|
||||
+ spin_unlock_bh(&ar->ab->base_lock);
|
||||
+ ath11k_warn(ar->ab, "failed to find peer to update txcompl mgmt stats\n");
|
||||
+ goto skip_mgmt_stats;
|
||||
+ }
|
||||
+
|
||||
+ vif = peer->vif;
|
||||
+ spin_unlock_bh(&ar->ab->base_lock);
|
||||
+
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+ arvif = ath11k_vif_to_arvif(vif);
|
||||
+ mgmt_stats = &arvif->mgmt_stats;
|
||||
+
|
||||
+ if (!tx_compl_param->status)
|
||||
+ mgmt_stats->tx_compl_succ[frm_type]++;
|
||||
+ else
|
||||
+ mgmt_stats->tx_compl_fail[frm_type]++;
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
+
|
||||
+skip_mgmt_stats:
|
||||
ieee80211_tx_status_irqsafe(ar->hw, msdu);
|
||||
|
||||
num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);
|
||||
@@ -7549,6 +7580,11 @@ static void ath11k_mgmt_rx_event(struct
|
||||
struct ieee80211_hdr *hdr;
|
||||
u16 fc;
|
||||
struct ieee80211_supported_band *sband;
|
||||
+ struct ath11k_peer *peer;
|
||||
+ struct ieee80211_vif *vif;
|
||||
+ struct ath11k_vif *arvif;
|
||||
+ struct ath11k_mgmt_frame_stats *mgmt_stats;
|
||||
+ u16 frm_type = 0;
|
||||
|
||||
if (ath11k_pull_mgmt_rx_params_tlv(ab, skb, &rx_ev) != 0) {
|
||||
ath11k_warn(ab, "failed to extract mgmt rx event");
|
||||
@@ -7614,7 +7650,34 @@ static void ath11k_mgmt_rx_event(struct
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
fc = le16_to_cpu(hdr->frame_control);
|
||||
+ frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, fc);
|
||||
+
|
||||
+ spin_lock_bh(&ab->base_lock);
|
||||
+
|
||||
+ peer = ath11k_peer_find_by_addr(ab, hdr->addr1);
|
||||
+ if(!peer)
|
||||
+ peer = ath11k_peer_find_by_addr(ab, hdr->addr3);
|
||||
+ if (!peer) {
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+ goto skip_mgmt_stats;
|
||||
+ }
|
||||
+
|
||||
+ vif = peer->vif;
|
||||
+
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+
|
||||
+ if (!vif)
|
||||
+ goto skip_mgmt_stats;
|
||||
+
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+
|
||||
+ arvif = ath11k_vif_to_arvif(vif);
|
||||
+ mgmt_stats = &arvif->mgmt_stats;
|
||||
+ mgmt_stats->rx_cnt[frm_type]++;
|
||||
+
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
+skip_mgmt_stats:
|
||||
/* Firmware is guaranteed to report all essential management frames via
|
||||
* WMI while it can deliver some extra via HTT. Since there can be
|
||||
* duplicates split the reporting wrt monitor/sniffing.
|
||||
@ -0,0 +1,146 @@
|
||||
From 41363c3109235a96d90d5946bbc01d1cc8dad47e Mon Sep 17 00:00:00 2001
|
||||
From: Anilkumar Kolli <akolli@codeaurora.org>
|
||||
Date: Sun, 6 Sep 2020 11:01:38 +0530
|
||||
Subject: [PATCH] ath11k: update debugfs support for mupltiple radios in PCI
|
||||
bus
|
||||
|
||||
debugfs_ath11k struct is moved to ath11k_core, since its common
|
||||
for both pci and ahb.
|
||||
|
||||
Current ath11k_pci insmod fails if there are multiple PCI rdaios,
|
||||
debugfs directory is created with soc_name and bus_id to allow
|
||||
creating debugfs directory for second PCI radio.
|
||||
|
||||
with this Debugfs entries looks like,
|
||||
# ls -l /sys/kernel/debug/ath11k/
|
||||
ipq8074 hw2.0 qcn9000 hw1.0_0000:01:00.0 qcn9000 hw1.0_0001:01:00.0
|
||||
|
||||
# ls -l /sys/kernel/debug/ath11k/ipq8074 hw2.0/
|
||||
mac0 mac1 simulate_fw_crash soc_dp_stats
|
||||
|
||||
# ls -l /sys/kernel/debug/ath11k/qcn9000 hw1.0_0000:01:00.0
|
||||
mac0 simulate_fw_crash soc_dp_stats
|
||||
|
||||
# /sys/kernel/debug/ath11k/qcn9000 hw1.0_0001:01:00.0:
|
||||
mac0 simulate_fw_crash soc_dp_stats
|
||||
|
||||
Signed-off-by: Anilkumar Kolli <akolli@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/core.c | 12 +++++++
|
||||
drivers/net/wireless/ath/ath11k/core.h | 1 -
|
||||
drivers/net/wireless/ath/ath11k/debugfs.c | 57 ++++++++++++++++++++++++------
|
||||
drivers/net/wireless/ath/ath11k/debugfs.h | 11 ++++++
|
||||
5 files changed, 72 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/core.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/core.c
|
||||
@@ -2367,5 +2367,17 @@ err_sc_free:
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_alloc);
|
||||
|
||||
+int ath11k_init(void)
|
||||
+{
|
||||
+ return ath11k_debugfs_create();
|
||||
+}
|
||||
+module_init(ath11k_init);
|
||||
+
|
||||
+void ath11k_exit(void)
|
||||
+{
|
||||
+ ath11k_debugfs_destroy();
|
||||
+}
|
||||
+module_exit(ath11k_exit);
|
||||
+
|
||||
MODULE_DESCRIPTION("Core module for Qualcomm Atheros 802.11ax wireless LAN cards.");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
|
||||
@@ -17,6 +17,8 @@
|
||||
#include "peer.h"
|
||||
#include "hif.h"
|
||||
|
||||
+struct dentry *debugfs_ath11k;
|
||||
+
|
||||
static const char *htt_bp_umac_ring[HTT_SW_UMAC_RING_IDX_MAX] = {
|
||||
"REO2SW1_RING",
|
||||
"REO2SW2_RING",
|
||||
@@ -992,8 +994,6 @@ int ath11k_debugfs_pdev_create(struct at
|
||||
|
||||
void ath11k_debugfs_pdev_destroy(struct ath11k_base *ab)
|
||||
{
|
||||
- debugfs_remove_recursive(ab->debugfs_soc);
|
||||
- ab->debugfs_soc = NULL;
|
||||
}
|
||||
|
||||
int ath11k_debugfs_soc_create(struct ath11k_base *ab)
|
||||
@@ -1046,6 +1046,24 @@ void ath11k_debugfs_soc_destroy(struct a
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_debugfs_soc_destroy);
|
||||
|
||||
+int ath11k_debugfs_create(void)
|
||||
+{
|
||||
+ debugfs_ath11k = debugfs_create_dir("ath11k", NULL);
|
||||
+ if (IS_ERR_OR_NULL(debugfs_ath11k)) {
|
||||
+ if (IS_ERR(debugfs_ath11k))
|
||||
+ return PTR_ERR(debugfs_ath11k);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void ath11k_debugfs_destroy(void)
|
||||
+{
|
||||
+ debugfs_remove_recursive(debugfs_ath11k);
|
||||
+ debugfs_ath11k = NULL;
|
||||
+}
|
||||
+
|
||||
void ath11k_debugfs_fw_stats_init(struct ath11k *ar)
|
||||
{
|
||||
struct dentry *fwstats_dir = debugfs_create_dir("fw_stats",
|
||||
@@ -1676,6 +1694,9 @@ int ath11k_debugfs_register(struct ath11
|
||||
char pdev_name[10];
|
||||
char buf[100] = {0};
|
||||
|
||||
+ if (!(IS_ERR_OR_NULL(ar->debug.debugfs_pdev)))
|
||||
+ return 0;
|
||||
+
|
||||
snprintf(pdev_name, sizeof(pdev_name), "%s%u", "mac", ar->pdev_idx);
|
||||
|
||||
ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
|
||||
@@ -1753,6 +1774,9 @@ void ath11k_debugfs_unregister(struct at
|
||||
kfree(dbr_debug);
|
||||
ar->debug.dbr_debug[i] = NULL;
|
||||
}
|
||||
+
|
||||
+ debugfs_remove_recursive(ar->debug.debugfs_pdev);
|
||||
+ ar->debug.debugfs_pdev = NULL;
|
||||
}
|
||||
|
||||
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
|
||||
@@ -264,6 +264,8 @@ struct ath11k_fw_dbglog {
|
||||
};
|
||||
|
||||
#ifdef CPTCFG_ATH11K_DEBUGFS
|
||||
+int ath11k_debugfs_create(void);
|
||||
+void ath11k_debugfs_destroy(void);
|
||||
int ath11k_debugfs_soc_create(struct ath11k_base *ab);
|
||||
void ath11k_debugfs_soc_destroy(struct ath11k_base *ab);
|
||||
int ath11k_debugfs_pdev_create(struct ath11k_base *ab);
|
||||
@@ -315,6 +317,15 @@ void ath11k_debugfs_add_dbring_entry(str
|
||||
struct hal_srng *srng);
|
||||
|
||||
#else
|
||||
+static inline int ath11k_debugfs_create(void)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline void ath11k_debugfs_destroy(void)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
static inline int ath11k_debugfs_soc_create(struct ath11k_base *ab)
|
||||
{
|
||||
return 0;
|
||||
@ -0,0 +1,21 @@
|
||||
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
||||
@@ -10214,6 +10214,8 @@ static int __ath11k_mac_register(struct
|
||||
wiphy_ext_feature_set(ar->hw->wiphy,
|
||||
NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
|
||||
|
||||
+ wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
|
||||
+
|
||||
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;
|
||||
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
@@ -4175,6 +4175,7 @@ ath11k_wmi_copy_resource_config(struct w
|
||||
wmi_cfg->max_bssid_rx_filters = tg_cfg->max_bssid_rx_filters;
|
||||
wmi_cfg->use_pdev_id = tg_cfg->use_pdev_id;
|
||||
wmi_cfg->flag1 = tg_cfg->flag1;
|
||||
+ wmi_cfg->flag1 |= WMI_RSRC_CFG_FLAG1_ACK_RSSI;
|
||||
wmi_cfg->peer_map_unmap_v2_support = tg_cfg->peer_map_unmap_v2_support;
|
||||
wmi_cfg->sched_params = tg_cfg->sched_params;
|
||||
wmi_cfg->twt_ap_pdev_count = tg_cfg->twt_ap_pdev_count;
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,162 @@
|
||||
From ed838800bb8f4c59b320395066ac356f74528a50 Mon Sep 17 00:00:00 2001
|
||||
From: Muna Sinada <msinada@codeaurora.org>
|
||||
Date: Wed, 29 Jul 2020 00:11:30 -0700
|
||||
Subject: [PATCH] 203-mac80211-ath11k-fw-dynamic-muedca.patch
|
||||
|
||||
mac80211/ath11k:FW Initiated Dynamic MU-EDCA
|
||||
|
||||
Implementing the updating of firmware initiated dynamic MU-EDCA
|
||||
parameters in Beacon IE. Firmware routinely checks its clients and
|
||||
updates its MU-EDCA values every 3 seconds. Firmware is tuning
|
||||
MU-EDCA parameters to improve performance. As part of this process,
|
||||
the firmware informs host about new MU-EDCA values utilizing
|
||||
WMI_MUEDCA_PARAMS_CONFIG_EVENTID. FW expectation is that host will
|
||||
update MU-EDCA parameters in the Beacon IE.
|
||||
Implementation consists of:
|
||||
(1) Receiving updated parameters through event in ATH11k
|
||||
(2) Passing updated parameters ATH11k -> mac80211 -> cfg80211
|
||||
(3) Passing updated parameters to user space.
|
||||
|
||||
Signed-off-by: Muna Sinada <msinada@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/wmi.c | 97 +++++++++++++++++++++++++++++++----
|
||||
drivers/net/wireless/ath/ath11k/wmi.h | 12 +++++
|
||||
include/net/cfg80211.h | 11 ++++
|
||||
include/net/mac80211.h | 13 +++++
|
||||
include/uapi/linux/nl80211.h | 10 ++++
|
||||
net/mac80211/mlme.c | 12 +++++
|
||||
net/mac80211/trace.h | 20 ++++++++
|
||||
net/wireless/nl80211.c | 36 +++++++++++++
|
||||
8 files changed, 200 insertions(+), 11 deletions(-)
|
||||
|
||||
--- 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_vdev_delete_resp_event) },
|
||||
[WMI_TAG_OBSS_COLOR_COLLISION_EVT] = {
|
||||
.min_len = sizeof(struct wmi_obss_color_collision_event) },
|
||||
+ [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] = {
|
||||
@@ -8809,6 +8811,74 @@ out:
|
||||
kfree(tb);
|
||||
}
|
||||
|
||||
+static void
|
||||
+ath11k_wmi_pdev_update_muedca_params_status_event(struct ath11k_base *ab,
|
||||
+ struct sk_buff *skb)
|
||||
+{
|
||||
+ const void **tb;
|
||||
+ const struct wmi_pdev_update_muedca_event *ev;
|
||||
+ struct ieee80211_mu_edca_param_set *params;
|
||||
+ struct ath11k *ar;
|
||||
+ int ret;
|
||||
+
|
||||
+ tb = ath11k_wmi_tlv_parse_alloc(ab, skb, 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_MUEDCA_PARAMS_CONFIG_EVENT];
|
||||
+ if (!ev) {
|
||||
+ ath11k_warn(ab, "failed to fetch pdev update muedca params ev");
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
+ "Update MU-EDCA parameters for pdev:%d\n", ev->pdev_id);
|
||||
+
|
||||
+ ar = ath11k_mac_get_ar_by_pdev_id(ab, ev->pdev_id);
|
||||
+ if (!ar) {
|
||||
+ ath11k_warn(ab,
|
||||
+ "MU-EDCA parameter change in invalid pdev %d\n",
|
||||
+ ev->pdev_id);
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ params = kzalloc(sizeof(*params), GFP_ATOMIC);
|
||||
+ if (!params) {
|
||||
+ ath11k_warn(ab,
|
||||
+ "Failed to allocate memory for updated MU-EDCA Parameters");
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ params->ac_be.aifsn = ev->aifsn[0];
|
||||
+ params->ac_be.ecw_min_max = ((0xF & ev->ecwmax[0]) << 4) |
|
||||
+ (0xF & ev->ecwmin[0]);
|
||||
+ params->ac_be.mu_edca_timer = ev->muedca_expiration_time[0];
|
||||
+
|
||||
+ params->ac_bk.aifsn = ev->aifsn[1];
|
||||
+ params->ac_bk.ecw_min_max = ((0xF & ev->ecwmax[1]) << 4) |
|
||||
+ (0xF & ev->ecwmin[1]);
|
||||
+ params->ac_bk.mu_edca_timer = ev->muedca_expiration_time[1];
|
||||
+
|
||||
+ params->ac_vi.aifsn = ev->aifsn[2];
|
||||
+ params->ac_vi.ecw_min_max = ((0xF & ev->ecwmax[2]) << 4) |
|
||||
+ (0xF & ev->ecwmin[2]);
|
||||
+ params->ac_vi.mu_edca_timer = ev->muedca_expiration_time[2];
|
||||
+
|
||||
+ params->ac_vo.aifsn = ev->aifsn[3];
|
||||
+ params->ac_vo.ecw_min_max = ((0xF & ev->ecwmax[3]) << 4) |
|
||||
+ (0xF & ev->ecwmin[3]);
|
||||
+ params->ac_vo.mu_edca_timer = ev->muedca_expiration_time[3];
|
||||
+
|
||||
+ ieee80211_update_muedca_params(ar->hw, params, GFP_ATOMIC);
|
||||
+
|
||||
+ kfree(params);
|
||||
+exit:
|
||||
+ kfree(tb);
|
||||
+}
|
||||
+
|
||||
static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_cmd_hdr *cmd_hdr;
|
||||
@@ -8927,6 +8997,9 @@ static void ath11k_wmi_tlv_op_rx(struct
|
||||
case WMI_11D_NEW_COUNTRY_EVENTID:
|
||||
ath11k_reg_11d_new_cc_event(ab, skb);
|
||||
break;
|
||||
+ case WMI_MUEDCA_PARAMS_CONFIG_EVENTID:
|
||||
+ ath11k_wmi_pdev_update_muedca_params_status_event(ab, skb);
|
||||
+ break;
|
||||
case WMI_DIAG_EVENTID:
|
||||
ath11k_wmi_diag_event(ab, skb);
|
||||
break;
|
||||
--- a/drivers/net/wireless/ath/ath11k/wmi.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
|
||||
@@ -772,6 +772,7 @@ enum wmi_tlv_event_id {
|
||||
WMI_READ_DATA_FROM_FLASH_EVENTID,
|
||||
WMI_REPORT_RX_AGGR_FAILURE_EVENTID,
|
||||
WMI_PKGID_EVENTID,
|
||||
+ WMI_MUEDCA_PARAMS_CONFIG_EVENTID = 0x1d01e,
|
||||
WMI_GPIO_INPUT_EVENTID = WMI_TLV_CMD(WMI_GRP_GPIO),
|
||||
WMI_UPLOADH_EVENTID,
|
||||
WMI_CAPTUREH_EVENTID,
|
||||
@@ -1884,6 +1885,7 @@ enum wmi_tlv_tag {
|
||||
WMI_TAG_NDP_EVENT,
|
||||
WMI_TAG_PDEV_PEER_PKTLOG_FILTER_CMD = 0x301,
|
||||
WMI_TAG_PDEV_PEER_PKTLOG_FILTER_INFO,
|
||||
+ WMI_TAG_MUEDCA_PARAMS_CONFIG_EVENT = 0x32a,
|
||||
WMI_TAG_FILS_DISCOVERY_TMPL_CMD = 0x344,
|
||||
WMI_TAG_PDEV_SRG_BSS_COLOR_BITMAP_CMD = 0x37b,
|
||||
WMI_TAG_PDEV_SRG_PARTIAL_BSSID_BITMAP_CMD,
|
||||
@@ -4896,6 +4898,16 @@ struct wmi_pdev_temperature_event {
|
||||
u32 pdev_id;
|
||||
} __packed;
|
||||
|
||||
+#define WMI_AC_MAX 4
|
||||
+
|
||||
+struct wmi_pdev_update_muedca_event {
|
||||
+ u32 pdev_id;
|
||||
+ u32 aifsn[WMI_AC_MAX];
|
||||
+ u32 ecwmin[WMI_AC_MAX];
|
||||
+ u32 ecwmax[WMI_AC_MAX];
|
||||
+ u32 muedca_expiration_time[WMI_AC_MAX];
|
||||
+} __packed;
|
||||
+
|
||||
#define WMI_RX_STATUS_OK 0x00
|
||||
#define WMI_RX_STATUS_ERR_CRC 0x01
|
||||
#define WMI_RX_STATUS_ERR_DECRYPT 0x08
|
||||
@ -0,0 +1,381 @@
|
||||
From 71add81f4a3f1ea505f498d789e7a1721c4d7a6e Mon Sep 17 00:00:00 2001
|
||||
From: Seevalamuthu Mariappan <seevalam@codeaurora.org>
|
||||
Date: Mon, 4 Sep 2023 12:48:19 +0530
|
||||
Subject: [PATCH] ath11k: Add support for dynamic vlan
|
||||
|
||||
This patch adds support for dynamic vlan. VLAN group traffics
|
||||
are encrypted in software. vlan unicast packets shall be taking
|
||||
8023 xmit path if encap offload is enabled and mcast/bcast will
|
||||
be using 80211 xmit path.
|
||||
|
||||
Metadata info in dp_tx added to notify firmware that the
|
||||
multicast/broadcast packets are encrypted in sw.
|
||||
|
||||
Signed-off-by: Seevalamuthu Mariappan <seevalam@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/core.h | 1 +
|
||||
drivers/net/wireless/ath/ath11k/dp_tx.c | 80 +++++++++-
|
||||
drivers/net/wireless/ath/ath11k/dp_tx.h | 198 ++++++++++++++++++++++++
|
||||
drivers/net/wireless/ath/ath11k/mac.c | 3 +
|
||||
4 files changed, 279 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/core.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
||||
@@ -125,6 +125,7 @@ struct ath11k_skb_cb {
|
||||
u32 cipher;
|
||||
struct ath11k *ar;
|
||||
struct ieee80211_vif *vif;
|
||||
+ u32 pkt_offset;
|
||||
} __packed;
|
||||
|
||||
struct ath11k_skb_rxcb {
|
||||
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
|
||||
@@ -79,6 +79,43 @@ enum hal_encrypt_type ath11k_dp_tx_get_e
|
||||
}
|
||||
}
|
||||
|
||||
+#define HTT_META_DATA_ALIGNMENT 0x8
|
||||
+
|
||||
+static int ath11k_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 ath11k_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 = ath11k_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 = 0;
|
||||
+ desc_ext->host_tx_desc_pool = 1;
|
||||
+ *htt_metadata_size = htt_desc_size_aligned;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
struct ath11k_sta *arsta, struct sk_buff *skb)
|
||||
{
|
||||
@@ -96,7 +133,8 @@ int ath11k_dp_tx(struct ath11k *ar, stru
|
||||
int ret;
|
||||
u32 ring_selector = 0;
|
||||
u8 ring_map = 0;
|
||||
- bool tcl_ring_retry;
|
||||
+ bool tcl_ring_retry, is_diff_encap = false;
|
||||
+ u8 align_pad, htt_meta_size = 0;
|
||||
|
||||
if (unlikely(test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags)))
|
||||
return -ESHUTDOWN;
|
||||
@@ -189,7 +227,10 @@ tcl_ring_sel:
|
||||
|
||||
switch (ti.encap_type) {
|
||||
case HAL_TCL_ENCAP_TYPE_NATIVE_WIFI:
|
||||
- ath11k_dp_tx_encap_nwifi(skb);
|
||||
+ if (arvif->vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
|
||||
+ is_diff_encap = true;
|
||||
+ else
|
||||
+ ath11k_dp_tx_encap_nwifi(skb);
|
||||
break;
|
||||
case HAL_TCL_ENCAP_TYPE_RAW:
|
||||
if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) {
|
||||
@@ -208,6 +249,33 @@ tcl_ring_sel:
|
||||
goto fail_remove_idr;
|
||||
}
|
||||
|
||||
+ /* Add metadata for sw encrypted vlan group traffic */
|
||||
+ 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)) {
|
||||
+ /* 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
|
||||
+ * to get 8-byte aligned start address along with align_pad added
|
||||
+ */
|
||||
+ align_pad = ((unsigned long)skb->data) & (HTT_META_DATA_ALIGNMENT - 1);
|
||||
+ ret = ath11k_dp_metadata_align_skb(skb, align_pad);
|
||||
+ if (unlikely(ret))
|
||||
+ goto fail_remove_idr;
|
||||
+
|
||||
+ ti.pkt_offset += align_pad;
|
||||
+ ret = ath11k_dp_prepare_htt_metadata(skb, &htt_meta_size);
|
||||
+ if (unlikely(ret))
|
||||
+ goto fail_remove_idr;
|
||||
+
|
||||
+ ti.pkt_offset += htt_meta_size;
|
||||
+ ti.meta_data_flags |= HTT_TCL_META_DATA_VALID_HTT;
|
||||
+ ti.flags0 |= FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_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);
|
||||
@@ -216,7 +284,8 @@ tcl_ring_sel:
|
||||
goto fail_remove_idr;
|
||||
}
|
||||
|
||||
- ti.data_len = skb->len;
|
||||
+ ti.data_len = skb->len - ti.pkt_offset;
|
||||
+ skb_cb->pkt_offset = ti.pkt_offset;
|
||||
skb_cb->paddr = ti.paddr;
|
||||
skb_cb->vif = arvif->vif;
|
||||
skb_cb->ar = ar;
|
||||
@@ -272,6 +341,8 @@ fail_unmap_dma:
|
||||
dma_unmap_single(ab->dev, ti.paddr, ti.data_len, DMA_TO_DEVICE);
|
||||
|
||||
fail_remove_idr:
|
||||
+ if (ti.pkt_offset)
|
||||
+ skb_pull(skb, ti.pkt_offset);
|
||||
spin_lock_bh(&tx_ring->tx_idr_lock);
|
||||
idr_remove(&tx_ring->txbuf_idr,
|
||||
FIELD_GET(DP_TX_DESC_ID_MSDU_ID, ti.desc_id));
|
||||
@@ -348,6 +419,9 @@ ath11k_dp_tx_htt_tx_complete_buf(struct
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (skb_cb->pkt_offset)
|
||||
+ skb_pull(msdu, skb_cb->pkt_offset); /* removing the alignment and htt meta data */
|
||||
+
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
if (ts->acked) {
|
||||
--- a/drivers/net/wireless/ath/ath11k/dp_tx.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.h
|
||||
@@ -17,6 +17,204 @@ struct ath11k_dp_htt_wbm_tx_status {
|
||||
u16 peer_id;
|
||||
};
|
||||
|
||||
+/* 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 ath11k_dp_tx_update_txcompl(struct ath11k *ar, struct hal_tx_status *ts);
|
||||
int ath11k_dp_tx_htt_h2t_ver_req_msg(struct ath11k_base *ab);
|
||||
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
|
||||
@@ -10405,6 +10405,9 @@ static int __ath11k_mac_register(struct
|
||||
*/
|
||||
ar->hw->wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MONITOR);
|
||||
|
||||
+ ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
|
||||
+ ar->hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);
|
||||
+
|
||||
/* Apply the regd received during initialization */
|
||||
ret = ath11k_regd_update(ar);
|
||||
if (ret) {
|
||||
@ -0,0 +1,354 @@
|
||||
From 1b402e444ff99efe84d09a084b96c39826783a8e Mon Sep 17 00:00:00 2001
|
||||
From: Ramya Gnanasekar <rgnanase@codeaurora.org>
|
||||
Date: Thu, 10 Sep 2020 13:33:55 +0530
|
||||
Subject: [PATCH] ath11k: Enable 512MB profile in ath11k
|
||||
|
||||
Below changes are made to enable 512MB mem mode in ath11k
|
||||
* Makefile changes to implement compilation flag when
|
||||
512MB mem profile is configured.
|
||||
* Enabling 512MB mem profile by default from Makefile
|
||||
for IPQ5018. This can be removed later once
|
||||
512MB profile config is supported.
|
||||
* Update target_mem_mode, number of stations, peer and vap
|
||||
during compile time
|
||||
|
||||
Signed-off-by: Ramya Gnanasekar <rgnanase@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/Kconfig | 7 +++++++
|
||||
drivers/net/wireless/ath/ath11k/hw.h | 14 +++++++++++---
|
||||
drivers/net/wireless/ath/ath11k/qmi.c | 2 +-
|
||||
drivers/net/wireless/ath/ath11k/qmi.h | 6 +++++-
|
||||
4 files changed, 24 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/Kconfig
|
||||
+++ b/drivers/net/wireless/ath/ath11k/Kconfig
|
||||
@@ -23,6 +23,20 @@ config ATH11K_NSS_SUPPORT
|
||||
|
||||
If unsure, say Y to enable NSS offload support.
|
||||
|
||||
+config ATH11K_MEM_PROFILE_512M
|
||||
+ bool "ath11k enable 512MB memory profile"
|
||||
+ depends on ATH11K
|
||||
+ default n
|
||||
+ ---help---
|
||||
+ Enables 512MB memory profile for ath11k
|
||||
+
|
||||
+config ATH11K_MEM_PROFILE_256M
|
||||
+ bool "ath11k enable 256MB memory profile"
|
||||
+ depends on ATH11K
|
||||
+ default n
|
||||
+ ---help---
|
||||
+ Enables 256MB memory profile for ath11k
|
||||
+
|
||||
config ATH11K_AHB
|
||||
tristate "Atheros ath11k AHB support"
|
||||
depends on m
|
||||
--- a/drivers/net/wireless/ath/ath11k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/hw.h
|
||||
@@ -11,11 +11,29 @@
|
||||
#include "wmi.h"
|
||||
|
||||
/* Target configuration defines */
|
||||
+#ifdef CPTCFG_ATH11K_MEM_PROFILE_512M
|
||||
|
||||
+#define TARGET_NUM_VDEVS(ab) 8
|
||||
+#define TARGET_NUM_PEERS_PDEV(ab) (128 + TARGET_NUM_VDEVS(ab))
|
||||
+/* Max num of stations (per radio) */
|
||||
+#define TARGET_NUM_STATIONS(ab) 128
|
||||
+#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
|
||||
+#define ATH11K_DP_RXDMA_MONITOR_BUF_RING_SIZE 128
|
||||
+#define ATH11K_DP_RXDMA_MONITOR_DST_RING_SIZE 128
|
||||
+#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))
|
||||
+/* Max num of stations (per radio) */
|
||||
+#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
|
||||
+#define ATH11K_DP_RXDMA_MONITOR_BUF_RING_SIZE 4096
|
||||
+#define ATH11K_DP_RXDMA_MONITOR_DST_RING_SIZE 2048
|
||||
+#endif
|
||||
|
||||
/* Num of peers for Single Radio mode */
|
||||
#define TARGET_NUM_PEERS_SINGLE(ab) (TARGET_NUM_PEERS_PDEV(ab))
|
||||
@@ -26,9 +44,6 @@
|
||||
/* Num of peers for DBS_SBS */
|
||||
#define TARGET_NUM_PEERS_DBS_SBS(ab) (3 * TARGET_NUM_PEERS_PDEV(ab))
|
||||
|
||||
-/* Max num of stations (per radio) */
|
||||
-#define TARGET_NUM_STATIONS(ab) (ab->hw_params.num_peers)
|
||||
-
|
||||
#define TARGET_NUM_PEERS(ab, x) TARGET_NUM_PEERS_##x(ab)
|
||||
#define TARGET_NUM_PEER_KEYS 2
|
||||
#define TARGET_NUM_TIDS(ab, x) (2 * TARGET_NUM_PEERS(ab, x) + \
|
||||
@@ -231,6 +246,7 @@ struct ath11k_hw_params {
|
||||
u32 tx_ring_size;
|
||||
bool smp2p_wow_exit;
|
||||
bool support_fw_mac_sequence;
|
||||
+ const struct ath11k_num_vdevs_peers *num_vdevs_peers;
|
||||
bool support_dual_stations;
|
||||
bool reo_status_poll;
|
||||
};
|
||||
--- a/drivers/net/wireless/ath/ath11k/qmi.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/qmi.h
|
||||
@@ -30,6 +30,12 @@
|
||||
#define ATH11K_QMI_BDF_EXT_STR_LENGTH 0x20
|
||||
#define ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT 5
|
||||
|
||||
+#ifdef CPTCFG_ATH11K_MEM_PROFILE_512M
|
||||
+#define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS 0x4E800000
|
||||
+#else
|
||||
+#define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS 0x51000000
|
||||
+#endif
|
||||
+
|
||||
#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 0x003E
|
||||
@@ -43,6 +49,11 @@
|
||||
#define ATH11K_QMI_DEVICE_BAR_SIZE 0x200000
|
||||
|
||||
struct ath11k_base;
|
||||
+enum ath11k_target_mem_mode {
|
||||
+ ATH11K_QMI_TARGET_MEM_MODE_DEFAULT = 0,
|
||||
+ ATH11K_QMI_TARGET_MEM_MODE_512M,
|
||||
+ ATH11K_QMI_TARGET_MEM_MODE_256M,
|
||||
+};
|
||||
|
||||
enum ath11k_qmi_file_type {
|
||||
ATH11K_QMI_FILE_TYPE_BDF_GOLDEN,
|
||||
--- a/local-symbols
|
||||
+++ b/local-symbols
|
||||
@@ -166,6 +166,8 @@ ATH11K=
|
||||
ATH11K_AHB=
|
||||
ATH11K_PCI=
|
||||
ATH11K_NSS_SUPPORT=
|
||||
+ATH11K_MEM_PROFILE_256M=
|
||||
+ATH11K_MEM_PROFILE_512M=
|
||||
ATH11K_DEBUG=
|
||||
ATH11K_DEBUGFS=
|
||||
ATH11K_TRACING=
|
||||
--- a/drivers/net/wireless/ath/ath11k/core.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <linux/average.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
-#include "fw.h"
|
||||
#include "qmi.h"
|
||||
#include "htc.h"
|
||||
#include "wmi.h"
|
||||
@@ -34,6 +33,7 @@
|
||||
#include "wow.h"
|
||||
#include "rx_desc.h"
|
||||
#include "nss.h"
|
||||
+#include "fw.h"
|
||||
|
||||
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
|
||||
|
||||
@@ -938,6 +938,11 @@ struct ath11k_msi_config {
|
||||
u16 hw_rev;
|
||||
};
|
||||
|
||||
+struct ath11k_num_vdevs_peers {
|
||||
+ u32 num_vdevs;
|
||||
+ u32 num_peers;
|
||||
+};
|
||||
+
|
||||
/* Master structure to hold the hw data which may be used in core module */
|
||||
struct ath11k_base {
|
||||
enum ath11k_hw_rev hw_rev;
|
||||
@@ -1095,6 +1100,8 @@ struct ath11k_base {
|
||||
DECLARE_BITMAP(fw_features, ATH11K_FW_FEATURE_COUNT);
|
||||
} fw;
|
||||
|
||||
+ atomic_t num_max_allowed;
|
||||
+
|
||||
#ifdef CPTCFG_NL80211_TESTMODE
|
||||
struct {
|
||||
u32 data_pos;
|
||||
--- a/drivers/net/wireless/ath/ath11k/dp.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/dp.h
|
||||
@@ -208,8 +208,9 @@ struct ath11k_pdev_dp {
|
||||
#define DP_WBM_RELEASE_RING_SIZE 64
|
||||
#define DP_TCL_DATA_RING_SIZE 512
|
||||
#define DP_TCL_DATA_RING_SIZE_WCN6750 2048
|
||||
-#define DP_TX_COMP_RING_SIZE 32768
|
||||
+#define DP_TX_COMP_RING_SIZE ATH11K_DP_TX_COMP_RING_SIZE
|
||||
#define DP_TX_IDR_SIZE DP_TX_COMP_RING_SIZE
|
||||
+#define DP_TX_COMP_MAX_ALLOWED DP_TX_COMP_RING_SIZE
|
||||
#define DP_TCL_CMD_RING_SIZE 32
|
||||
#define DP_TCL_STATUS_RING_SIZE 32
|
||||
#define DP_REO_DST_RING_MAX 4
|
||||
@@ -222,9 +223,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
|
||||
-#define DP_RXDMA_MON_STATUS_RING_SIZE 1024
|
||||
-#define DP_RXDMA_MONITOR_BUF_RING_SIZE 4096
|
||||
-#define DP_RXDMA_MONITOR_DST_RING_SIZE 2048
|
||||
+#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
|
||||
+#define DP_RXDMA_MONITOR_DST_RING_SIZE ATH11K_DP_RXDMA_MONITOR_BUF_RING_SIZE
|
||||
#define DP_RXDMA_MONITOR_DESC_RING_SIZE 4096
|
||||
|
||||
#define DP_RX_RELEASE_RING_NUM 3
|
||||
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
|
||||
@@ -334,6 +334,7 @@ tcl_ring_sel:
|
||||
skb->data, skb->len);
|
||||
|
||||
atomic_inc(&ar->dp.num_tx_pending);
|
||||
+ atomic_inc(&ab->num_max_allowed);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -380,6 +381,7 @@ 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);
|
||||
+ atomic_dec(&ab->num_max_allowed);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -411,6 +413,7 @@ 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);
|
||||
+ atomic_dec(&ab->num_max_allowed);
|
||||
|
||||
dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
|
||||
|
||||
@@ -833,6 +836,7 @@ void ath11k_dp_tx_completion_handler(str
|
||||
wake_up(&ar->dp.tx_empty_waitq);
|
||||
|
||||
ath11k_dp_tx_complete_msdu(ar, msdu, &ts);
|
||||
+ atomic_dec(&ab->num_max_allowed);
|
||||
}
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/core.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/core.c
|
||||
@@ -43,6 +43,8 @@ bool ath11k_ftm_mode;
|
||||
module_param_named(ftm_mode, ath11k_ftm_mode, bool, 0444);
|
||||
MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode");
|
||||
|
||||
+static const struct ath11k_num_vdevs_peers ath11k_vdevs_peers[];
|
||||
+
|
||||
static struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
{
|
||||
.hw_rev = ATH11K_HW_IPQ8074,
|
||||
@@ -128,6 +130,7 @@ static struct ath11k_hw_params ath11k_hw
|
||||
.tcl_ring_retry = true,
|
||||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
+ .num_vdevs_peers = ath11k_vdevs_peers,
|
||||
.support_dual_stations = false,
|
||||
},
|
||||
{
|
||||
@@ -179,7 +182,7 @@ static struct ath11k_hw_params ath11k_hw
|
||||
.coldboot_cal_mm = false,
|
||||
.coldboot_cal_ftm = false,
|
||||
.cbcal_restart_fw = true,
|
||||
- .fw_mem_mode = 0,
|
||||
+ .fw_mem_mode = ATH11K_QMI_TARGET_MEM_MODE,
|
||||
.num_vdevs = 16 + 1,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = false,
|
||||
@@ -265,7 +268,7 @@ static struct ath11k_hw_params ath11k_hw
|
||||
.coldboot_cal_mm = false,
|
||||
.coldboot_cal_ftm = false,
|
||||
.cbcal_restart_fw = false,
|
||||
- .fw_mem_mode = 0,
|
||||
+ .fw_mem_mode = ATH11K_QMI_TARGET_MEM_MODE,
|
||||
.num_vdevs = 2 + 1,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = true,
|
||||
@@ -437,7 +440,7 @@ static struct ath11k_hw_params ath11k_hw
|
||||
.coldboot_cal_mm = false,
|
||||
.coldboot_cal_ftm = false,
|
||||
.cbcal_restart_fw = false,
|
||||
- .fw_mem_mode = 0,
|
||||
+ .fw_mem_mode = ATH11K_QMI_TARGET_MEM_MODE,
|
||||
.num_vdevs = 2 + 1,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = true,
|
||||
@@ -473,6 +476,7 @@ static struct ath11k_hw_params ath11k_hw
|
||||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
.support_fw_mac_sequence = true,
|
||||
+ .num_vdevs_peers = ath11k_vdevs_peers,
|
||||
.support_dual_stations = true,
|
||||
},
|
||||
{
|
||||
@@ -524,7 +528,7 @@ static struct ath11k_hw_params ath11k_hw
|
||||
.coldboot_cal_mm = false,
|
||||
.coldboot_cal_ftm = false,
|
||||
.cbcal_restart_fw = false,
|
||||
- .fw_mem_mode = 0,
|
||||
+ .fw_mem_mode = ATH11K_QMI_TARGET_MEM_MODE,
|
||||
.num_vdevs = 2 + 1,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = true,
|
||||
@@ -560,6 +564,7 @@ static struct ath11k_hw_params ath11k_hw
|
||||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
.support_fw_mac_sequence = true,
|
||||
+ .num_vdevs_peers = ath11k_vdevs_peers,
|
||||
.support_dual_stations = true,
|
||||
},
|
||||
{
|
||||
@@ -609,7 +614,7 @@ static struct ath11k_hw_params ath11k_hw
|
||||
.coldboot_cal_mm = true,
|
||||
.coldboot_cal_ftm = true,
|
||||
.cbcal_restart_fw = false,
|
||||
- .fw_mem_mode = 0,
|
||||
+ .fw_mem_mode = ATH11K_QMI_TARGET_MEM_MODE,
|
||||
.num_vdevs = 3,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = false,
|
||||
@@ -689,7 +694,7 @@ static struct ath11k_hw_params ath11k_hw
|
||||
.supports_monitor = false,
|
||||
.supports_sta_ps = false,
|
||||
.supports_shadow_regs = false,
|
||||
- .fw_mem_mode = 0,
|
||||
+ .fw_mem_mode = ATH11K_QMI_TARGET_MEM_MODE,
|
||||
.num_vdevs = 16 + 1,
|
||||
.num_peers = 512,
|
||||
.supports_regdb = false,
|
||||
@@ -724,6 +729,7 @@ static struct ath11k_hw_params ath11k_hw
|
||||
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
|
||||
.smp2p_wow_exit = false,
|
||||
.support_fw_mac_sequence = false,
|
||||
+ .num_vdevs_peers = ath11k_vdevs_peers,
|
||||
.support_dual_stations = false,
|
||||
.reo_status_poll = true,
|
||||
},
|
||||
@@ -881,6 +887,21 @@ static struct ath11k_hw_params ath11k_hw
|
||||
},
|
||||
};
|
||||
|
||||
+static const struct ath11k_num_vdevs_peers ath11k_vdevs_peers[] = {
|
||||
+ {
|
||||
+ .num_vdevs = (16 + 1),
|
||||
+ .num_peers = 512,
|
||||
+ },
|
||||
+ {
|
||||
+ .num_vdevs = (8 + 1),
|
||||
+ .num_peers = 128,
|
||||
+ },
|
||||
+ {
|
||||
+ .num_vdevs = 8,
|
||||
+ .num_peers = 128,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
static inline struct ath11k_pdev *ath11k_core_get_single_pdev(struct ath11k_base *ab)
|
||||
{
|
||||
WARN_ON(!ab->hw_params.single_pdev_only);
|
||||
@ -0,0 +1,688 @@
|
||||
From d4c3b17e66243a2d6d8845192453ef7da568bac2 Mon Sep 17 00:00:00 2001
|
||||
From: Sathishkumar Muruganandam <murugana@codeaurora.org>
|
||||
Date: Thu, 10 Sep 2020 15:58:53 +0530
|
||||
Subject: [PATCH 1/2] ath11k: add WDS offload changes to NSS driver interface
|
||||
|
||||
add WDS and MEC AST handling to NSS
|
||||
|
||||
Signed-off-by: Sathishkumar Muruganandam <murugana@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/nss.c | 465 ++++++++++++++++++++++++++++++++--
|
||||
drivers/net/wireless/ath/ath11k/nss.h | 36 ++-
|
||||
2 files changed, 473 insertions(+), 28 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/nss.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/nss.c
|
||||
@@ -307,6 +307,22 @@ void ath11k_nss_wifili_event_receive(str
|
||||
case NSS_WIFILI_TID_REOQ_SETUP_MSG:
|
||||
/* TODO setup tidq */
|
||||
break;
|
||||
+ case NSS_WIFILI_WDS_PEER_ADD_MSG:
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS, "nss wifili wds peer add event received %d response %d error %d\n",
|
||||
+ msg_type, response, error);
|
||||
+ break;
|
||||
+ case NSS_WIFILI_WDS_PEER_UPDATE_MSG:
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS, "nss wifili wds peer update event received %d response %d error %d\n",
|
||||
+ msg_type, response, error);
|
||||
+ break;
|
||||
+ case NSS_WIFILI_WDS_PEER_MAP_MSG:
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS, "nss wifili wds peer map event received %d response %d error %d\n",
|
||||
+ msg_type, response, error);
|
||||
+ break;
|
||||
+ case NSS_WIFILI_WDS_PEER_DEL_MSG:
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS, "nss wifili wds peer del event received %d response %d error %d\n",
|
||||
+ msg_type, response, error);
|
||||
+ break;
|
||||
default:
|
||||
ath11k_dbg(ab, ATH11K_DBG_NSS, "unhandled event %d\n", msg_type);
|
||||
break;
|
||||
@@ -417,13 +433,6 @@ static void ath11k_nss_vdev_event_receiv
|
||||
/*TODO*/
|
||||
}
|
||||
|
||||
-static void
|
||||
-ath11k_nss_vdev_special_data_receive(struct net_device *dev, struct sk_buff *skb,
|
||||
- __attribute__((unused)) struct napi_struct *napi)
|
||||
-{
|
||||
- /* TODO */
|
||||
-}
|
||||
-
|
||||
/* TODO: move to mac80211 after cleanups/refactoring required after feature completion */
|
||||
static int ath11k_nss_deliver_rx(struct ieee80211_vif *vif, struct sk_buff *skb,
|
||||
bool eth, int data_offs, struct napi_struct *napi)
|
||||
@@ -547,11 +556,239 @@ static int ath11k_nss_undecap_nwifi(stru
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void ath11k_nss_wds_type_rx(struct ath11k *ar, u8* src_mac, u8 is_sa_valid,
|
||||
+ u8 addr4_valid, u16 peer_id)
|
||||
+{
|
||||
+ struct ath11k_base *ab = ar->ab;
|
||||
+ struct ath11k_ast_entry *ast_entry = NULL;
|
||||
+ struct ath11k_peer *ta_peer = NULL;
|
||||
+
|
||||
+ spin_lock_bh(&ab->base_lock);
|
||||
+ ta_peer = ath11k_peer_find_by_id(ab, peer_id);
|
||||
+
|
||||
+ if (!ta_peer) {
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,"ath11k_nss_wds_type_rx ta_peer %pM\n",
|
||||
+ ta_peer->addr);
|
||||
+
|
||||
+ if (addr4_valid) {
|
||||
+ ast_entry = ath11k_peer_ast_find_by_addr(ab, src_mac);
|
||||
+ if (!is_sa_valid) {
|
||||
+ ath11k_peer_add_ast(ar, ta_peer, src_mac,
|
||||
+ ATH11K_AST_TYPE_WDS);
|
||||
+ ath11k_nss_add_wds_peer(ar, ta_peer,
|
||||
+ src_mac, ATH11K_AST_TYPE_WDS);
|
||||
+ } else {
|
||||
+ if (!ast_entry) {
|
||||
+ ath11k_peer_add_ast(ar, ta_peer, src_mac,
|
||||
+ ATH11K_AST_TYPE_WDS);
|
||||
+ ath11k_nss_add_wds_peer(ar, ta_peer, src_mac,
|
||||
+ ATH11K_AST_TYPE_WDS);
|
||||
+ } else {
|
||||
+ ath11k_peer_update_ast(ar, ta_peer, ast_entry);
|
||||
+ ath11k_nss_update_wds_peer(ar, ta_peer, src_mac);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+}
|
||||
+
|
||||
+static void ath11k_nss_mec_handler(struct ath11k *ar, u8* mec_mac_addr)
|
||||
+{
|
||||
+ struct ath11k_base *ab = ar->ab;
|
||||
+ struct ath11k_peer *peer = ar->bss_peer;
|
||||
+ u8 mac_addr[ETH_ALEN];
|
||||
+ u32 *mac_addr_l32;
|
||||
+ u16 *mac_addr_h16;
|
||||
+
|
||||
+ if (!peer)
|
||||
+ return;
|
||||
+
|
||||
+ /* mec_mac_addr has the swapped mac_addr after 4 bytes (sizeof(u32))
|
||||
+ * mec_mac_addr[0]
|
||||
+ * |
|
||||
+ * 03:0a:00:00:2d:15:22:f0:fd:8c
|
||||
+ * ^
|
||||
+ * Swapped MAC address present after 4 bytes
|
||||
+ * MAC address after swapping is 8c:fd:f0:22:15:2d */
|
||||
+
|
||||
+ mac_addr_l32 = (u32 *) (mec_mac_addr + sizeof(u32));
|
||||
+ mac_addr_h16 = (u16 *) (mec_mac_addr + sizeof(u32) + sizeof(u32));
|
||||
+
|
||||
+ *mac_addr_l32 = swab32(*mac_addr_l32);
|
||||
+ *mac_addr_h16 = swab16(*mac_addr_h16);
|
||||
+
|
||||
+ memcpy(mac_addr, mac_addr_h16, ETH_ALEN - 4);
|
||||
+ memcpy(mac_addr + 2, mac_addr_l32, 4);
|
||||
+
|
||||
+ if (!ether_addr_equal(ar->mac_addr, mac_addr)) {
|
||||
+ spin_lock_bh(&ab->base_lock);
|
||||
+ ath11k_peer_add_ast(ar, peer, mac_addr,
|
||||
+ ATH11K_AST_TYPE_MEC);
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void ath11k_nss_vdev_spl_receive_ext_wdsdata(struct ath11k_vif *arvif,
|
||||
+ struct sk_buff *skb,
|
||||
+ struct nss_wifi_vdev_wds_per_packet_metadata *wds_metadata)
|
||||
+{
|
||||
+ struct ath11k *ar = arvif->ar;
|
||||
+ struct ath11k_base *ab = ar->ab;
|
||||
+ enum wifi_vdev_ext_wds_info_type wds_type;
|
||||
+ u8 is_sa_valid = 0, addr4_valid = 0;
|
||||
+ u16 peer_id;
|
||||
+ u8 src_mac[ETH_ALEN];
|
||||
+
|
||||
+ is_sa_valid = wds_metadata->is_sa_valid;
|
||||
+ addr4_valid = wds_metadata->addr4_valid;
|
||||
+ wds_type = wds_metadata->wds_type;
|
||||
+ peer_id = wds_metadata->peer_id;
|
||||
+
|
||||
+ memcpy(src_mac, ((struct ethhdr *)skb->data)->h_source, ETH_ALEN);
|
||||
+
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,"receive_ext_wdsdata wds_type %d peer id %u sa_valid %d addr4_valid %d src_mac %pM\n",
|
||||
+ wds_type, peer_id, is_sa_valid, addr4_valid, src_mac);
|
||||
+
|
||||
+ switch (wds_type) {
|
||||
+ case NSS_WIFI_VDEV_WDS_TYPE_RX:
|
||||
+ ath11k_nss_wds_type_rx(ar, src_mac, is_sa_valid,
|
||||
+ addr4_valid, peer_id);
|
||||
+ break;
|
||||
+ case NSS_WIFI_VDEV_WDS_TYPE_MEC:
|
||||
+ ath11k_nss_mec_handler(ar, (u8 *)(skb->data));
|
||||
+ break;
|
||||
+ default:
|
||||
+ ath11k_warn(ab, "unsupported wds_type %d\n", wds_type);
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static bool ath11k_nss_vdev_data_receive_mec_check(struct ath11k *ar,
|
||||
+ struct sk_buff *skb)
|
||||
+{
|
||||
+ struct ath11k_base *ab = ar->ab;
|
||||
+ struct ath11k_ast_entry *ast_entry = NULL;
|
||||
+ u8 src_mac[ETH_ALEN];
|
||||
+
|
||||
+ memcpy(src_mac, ((struct ethhdr *)skb->data)->h_source, ETH_ALEN);
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
||||
+ "ath11k_nss_vdev_data_receive_mec_check src mac %pM\n",
|
||||
+ src_mac);
|
||||
+
|
||||
+ spin_lock_bh(&ab->base_lock);
|
||||
+ ast_entry = ath11k_peer_ast_find_by_addr(ab, src_mac);
|
||||
+
|
||||
+ if (ast_entry && ast_entry->type == ATH11K_AST_TYPE_MEC) {
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
||||
+ "dropping mec traffic from %pM\n", ast_entry->addr);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static int ath11k_nss_undecap(struct ath11k_vif *arvif, struct sk_buff *skb,
|
||||
+ int *data_offs, bool *eth_decap)
|
||||
+{
|
||||
+ enum ath11k_hw_txrx_mode decap_type;
|
||||
+
|
||||
+ decap_type = arvif->nss.decap;
|
||||
+
|
||||
+ switch (decap_type) {
|
||||
+ case ATH11K_HW_TXRX_RAW:
|
||||
+ return ath11k_nss_undecap_raw(arvif, skb, data_offs);
|
||||
+ case ATH11K_HW_TXRX_NATIVE_WIFI:
|
||||
+ return ath11k_nss_undecap_nwifi(arvif, skb, data_offs);
|
||||
+ case ATH11K_HW_TXRX_ETHERNET:
|
||||
+ *eth_decap = true;
|
||||
+ return 0;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+ath11k_nss_vdev_special_data_receive(struct net_device *dev, struct sk_buff *skb,
|
||||
+ __attribute__((unused)) struct napi_struct *napi)
|
||||
+{
|
||||
+ struct nss_wifi_vdev_per_packet_metadata *wifi_metadata = NULL;
|
||||
+ struct nss_wifi_vdev_wds_per_packet_metadata *wds_metadata = NULL;
|
||||
+ struct wireless_dev *wdev;
|
||||
+ struct ieee80211_vif *vif;
|
||||
+ struct ath11k_vif *arvif;
|
||||
+ struct ath11k_base *ab;
|
||||
+ bool eth_decap = false;
|
||||
+ int data_offs = 0;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ 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;
|
||||
+
|
||||
+ dma_unmap_single(ab->dev, virt_to_phys(skb->head),
|
||||
+ NSS_WIFI_VDEV_PER_PACKET_METADATA_OFFSET +
|
||||
+ sizeof(struct nss_wifi_vdev_per_packet_metadata),
|
||||
+ DMA_FROM_DEVICE);
|
||||
+
|
||||
+ wifi_metadata = (struct nss_wifi_vdev_per_packet_metadata *)(skb->head +
|
||||
+ NSS_WIFI_VDEV_PER_PACKET_METADATA_OFFSET);
|
||||
+
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
||||
+ "dp special data from nss: wifi_metadata->pkt_type %d",
|
||||
+ wifi_metadata->pkt_type);
|
||||
+
|
||||
+ ret = ath11k_nss_undecap(arvif, skb, &data_offs, ð_decap);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ab, "error in nss rx undecap, type %d err %d\n",
|
||||
+ arvif->nss.decap, ret);
|
||||
+ dev_kfree_skb_any(skb);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (eth_decap && wifi_metadata->pkt_type ==
|
||||
+ NSS_WIFI_VDEV_EXT_DATA_PKT_TYPE_WDS_LEARN) {
|
||||
+ wds_metadata = &wifi_metadata->metadata.wds_metadata;
|
||||
+ ath11k_nss_vdev_spl_receive_ext_wdsdata(arvif, skb,
|
||||
+ wds_metadata);
|
||||
+ }
|
||||
+
|
||||
+ ath11k_nss_deliver_rx(arvif->vif, skb, eth_decap, data_offs, napi);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
ath11k_nss_vdev_data_receive(struct net_device *dev, struct sk_buff *skb,
|
||||
__attribute__((unused)) struct napi_struct *napi)
|
||||
{
|
||||
- enum ath11k_hw_txrx_mode decap_type;
|
||||
struct wireless_dev *wdev = NULL;
|
||||
struct ieee80211_vif *vif = NULL;
|
||||
struct ath11k_vif *arvif;
|
||||
@@ -591,28 +828,16 @@ ath11k_nss_vdev_data_receive(struct net_
|
||||
ath11k_dbg_dump(ab, ATH11K_DBG_DP_RX, "", "dp rx msdu from nss: ",
|
||||
skb->data, skb->len);
|
||||
|
||||
- decap_type = arvif->nss.decap;
|
||||
-
|
||||
- switch (decap_type) {
|
||||
- case ATH11K_HW_TXRX_RAW:
|
||||
- ret = ath11k_nss_undecap_raw(arvif, skb, &data_offs);
|
||||
- break;
|
||||
- case ATH11K_HW_TXRX_NATIVE_WIFI:
|
||||
- ret = ath11k_nss_undecap_nwifi(arvif, skb, &data_offs);
|
||||
- break;
|
||||
- case ATH11K_HW_TXRX_ETHERNET:
|
||||
- /* no changes required for ethernet decap */
|
||||
- ret = 0;
|
||||
- eth_decap = true;
|
||||
- break;
|
||||
- default:
|
||||
- ret = -EINVAL;
|
||||
- break;
|
||||
+ if ((vif->type == NL80211_IFTYPE_STATION && wdev->use_4addr) &&
|
||||
+ ath11k_nss_vdev_data_receive_mec_check(arvif->ar, skb)) {
|
||||
+ dev_kfree_skb_any(skb);
|
||||
+ return;
|
||||
}
|
||||
|
||||
+ ret = ath11k_nss_undecap(arvif, skb, &data_offs, ð_decap);
|
||||
if (ret) {
|
||||
- ath11k_warn(ab, "error in nss rx undecap, type %d err %d\n", decap_type,
|
||||
- ret);
|
||||
+ ath11k_warn(ab, "error in nss rx undecap, type %d err %d\n",
|
||||
+ arvif->nss.decap, ret);
|
||||
dev_kfree_skb_any(skb);
|
||||
return;
|
||||
}
|
||||
@@ -1324,7 +1549,7 @@ void ath11k_nss_update_sta_rxrate(struct
|
||||
peer->nss.nss_stats->rxrate.bw = ath11k_mac_bw_to_mac80211_bw(ppdu_info->bw);
|
||||
}
|
||||
|
||||
-int ath11k_nss_peer_delete(struct ath11k_base *ab, const u8 *addr)
|
||||
+int ath11k_nss_peer_delete(struct ath11k_base *ab, u32 vdev_id, const u8 *addr)
|
||||
{
|
||||
struct nss_wifili_peer_msg *peer_msg;
|
||||
struct nss_wifili_msg *wlmsg = NULL;
|
||||
@@ -1338,9 +1563,10 @@ int ath11k_nss_peer_delete(struct ath11k
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
|
||||
- peer = ath11k_peer_find_by_addr(ab, addr);
|
||||
+ peer = ath11k_peer_find(ab, vdev_id, addr);
|
||||
if (!peer) {
|
||||
- ath11k_warn(ab, "peer (%pM) not found for nss peer delete\n", addr);
|
||||
+ ath11k_warn(ab, "peer (%pM) not found on vdev_id %d for nss peer delete\n",
|
||||
+ addr, vdev_id);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1413,8 +1639,9 @@ free_peer:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-int ath11k_nss_peer_create(struct ath11k_base *ab, struct ath11k_peer *peer)
|
||||
+int ath11k_nss_peer_create(struct ath11k *ar, struct ath11k_peer *peer)
|
||||
{
|
||||
+ struct ath11k_base *ab = ar->ab;
|
||||
struct nss_wifili_peer_msg *peer_msg;
|
||||
struct nss_wifili_msg *wlmsg = NULL;
|
||||
nss_wifili_msg_callback_t msg_cb;
|
||||
@@ -1471,17 +1698,23 @@ int ath11k_nss_peer_create(struct ath11k
|
||||
status = nss_wifili_tx_msg(ab->nss.ctx, wlmsg);
|
||||
if (status != NSS_TX_SUCCESS) {
|
||||
ret = -EINVAL;
|
||||
- ath11k_warn(ab, "nss send peer (%pM) create msg tx error\n",
|
||||
- peer->addr);
|
||||
+ ath11k_warn(ab, "nss send peer (%pM) create msg tx error: %d\n",
|
||||
+ peer->addr, status);
|
||||
goto peer_mem_free;
|
||||
}
|
||||
|
||||
- ret = 0;
|
||||
ath11k_dbg(ab, ATH11K_DBG_NSS,
|
||||
"nss peer_create msg success mac:%pM vdev:%d peer_id:%d hw_ast_idx:%d ast_hash:%d\n",
|
||||
peer_msg->peer_mac_addr, peer_msg->vdev_id, peer_msg->peer_id,
|
||||
peer_msg->hw_ast_idx, peer_msg->tx_ast_hash);
|
||||
|
||||
+ ret = ath11k_peer_add_ast(ar, peer, peer->addr,
|
||||
+ ATH11K_AST_TYPE_STATIC);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ab, "failed to add STATIC ast: %d\n", ret);
|
||||
+ goto peer_mem_free;
|
||||
+ }
|
||||
+
|
||||
peer->nss.nss_stats = kzalloc(sizeof(*peer->nss.nss_stats), GFP_ATOMIC);
|
||||
if (!peer->nss.nss_stats) {
|
||||
ret = -ENOMEM;
|
||||
@@ -1500,6 +1733,199 @@ msg_free:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+int ath11k_nss_add_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
+ u8 *dest_mac, enum ath11k_ast_entry_type type)
|
||||
+{
|
||||
+ struct ath11k_base *ab = ar->ab;
|
||||
+ struct nss_wifili_wds_peer_msg *wds_peer_msg;
|
||||
+ struct nss_wifili_msg *wlmsg = NULL;
|
||||
+ nss_wifili_msg_callback_t msg_cb;
|
||||
+ nss_tx_status_t status;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC);
|
||||
+ if (wlmsg == NULL)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ wds_peer_msg = &wlmsg->msg.wdspeermsg;
|
||||
+
|
||||
+ wds_peer_msg->pdev_id = ar->pdev->pdev_id;
|
||||
+ wds_peer_msg->ast_type = type;
|
||||
+ wds_peer_msg->peer_id = peer->peer_id;
|
||||
+
|
||||
+ if (type == ATH11K_AST_TYPE_MEC)
|
||||
+ ether_addr_copy(wds_peer_msg->peer_mac, ar->mac_addr);
|
||||
+ else
|
||||
+ ether_addr_copy(wds_peer_msg->peer_mac, peer->addr);
|
||||
+
|
||||
+ ether_addr_copy(wds_peer_msg->dest_mac, dest_mac);
|
||||
+
|
||||
+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive;
|
||||
+
|
||||
+ nss_cmn_msg_init(&wlmsg->cm, ab->nss.if_num,
|
||||
+ NSS_WIFILI_WDS_PEER_ADD_MSG,
|
||||
+ sizeof(struct nss_wifili_wds_peer_msg),
|
||||
+ msg_cb, NULL);
|
||||
+
|
||||
+ status = nss_wifili_tx_msg(ab->nss.ctx, wlmsg);
|
||||
+ if (status != NSS_TX_SUCCESS) {
|
||||
+ ret = -EINVAL;
|
||||
+ ath11k_warn(ab, "nss send wds add peer msg tx error: %d\n",
|
||||
+ status);
|
||||
+ goto msg_free;
|
||||
+ }
|
||||
+
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
||||
+ "nss add wds peer success peer mac:%pM dest mac:%pM peer_id:%d\n",
|
||||
+ wds_peer_msg->peer_mac, wds_peer_msg->dest_mac, wds_peer_msg->peer_id);
|
||||
+
|
||||
+msg_free:
|
||||
+ kfree(wlmsg);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int ath11k_nss_update_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
+ u8 *dest_mac)
|
||||
+{
|
||||
+ struct ath11k_base *ab = ar->ab;
|
||||
+ struct nss_wifili_wds_peer_msg *wds_peer_msg;
|
||||
+ struct nss_wifili_msg *wlmsg = NULL;
|
||||
+ nss_wifili_msg_callback_t msg_cb;
|
||||
+ nss_tx_status_t status;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC);
|
||||
+ if (wlmsg == NULL)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ wds_peer_msg = &wlmsg->msg.wdspeermsg;
|
||||
+
|
||||
+ wds_peer_msg->pdev_id = ar->pdev->pdev_id;
|
||||
+ wds_peer_msg->ast_type = ATH11K_AST_TYPE_WDS;
|
||||
+ wds_peer_msg->peer_id = peer->peer_id;
|
||||
+ ether_addr_copy(wds_peer_msg->peer_mac, peer->addr);
|
||||
+ ether_addr_copy(wds_peer_msg->dest_mac, dest_mac);
|
||||
+
|
||||
+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive;
|
||||
+
|
||||
+ nss_cmn_msg_init(&wlmsg->cm, ab->nss.if_num,
|
||||
+ NSS_WIFILI_WDS_PEER_UPDATE_MSG,
|
||||
+ sizeof(struct nss_wifili_wds_peer_msg),
|
||||
+ msg_cb, NULL);
|
||||
+
|
||||
+ status = nss_wifili_tx_msg(ab->nss.ctx, wlmsg);
|
||||
+ if (status != NSS_TX_SUCCESS) {
|
||||
+ ret = -EINVAL;
|
||||
+ ath11k_warn(ab, "nss send wds update peer msg tx error: %d\n",
|
||||
+ status);
|
||||
+ goto msg_free;
|
||||
+ }
|
||||
+
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
||||
+ "nss update wds peer success peer mac:%pM dest mac:%pM peer_id:%d\n",
|
||||
+ wds_peer_msg->peer_mac, wds_peer_msg->dest_mac, wds_peer_msg->peer_id);
|
||||
+
|
||||
+msg_free:
|
||||
+ kfree(wlmsg);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int ath11k_nss_map_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
+ u8 *dest_mac, enum ath11k_ast_entry_type type)
|
||||
+{
|
||||
+ 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;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC);
|
||||
+ if (wlmsg == NULL)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ 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;
|
||||
+
|
||||
+ if (type == ATH11K_AST_TYPE_MEC)
|
||||
+ wds_peer_map_msg->peer_id = NSS_WIFILI_MEC_PEER_ID;
|
||||
+ else
|
||||
+ wds_peer_map_msg->peer_id = peer->peer_id;
|
||||
+
|
||||
+ ether_addr_copy(wds_peer_map_msg->dest_mac, dest_mac);
|
||||
+
|
||||
+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive;
|
||||
+
|
||||
+ nss_cmn_msg_init(&wlmsg->cm, ab->nss.if_num,
|
||||
+ NSS_WIFILI_WDS_PEER_MAP_MSG,
|
||||
+ sizeof(struct nss_wifili_wds_peer_map_msg),
|
||||
+ msg_cb, NULL);
|
||||
+
|
||||
+ status = nss_wifili_tx_msg(ab->nss.ctx, wlmsg);
|
||||
+ if (status != NSS_TX_SUCCESS) {
|
||||
+ ret = -EINVAL;
|
||||
+ ath11k_warn(ab, "nss send wds peer map msg tx error: %d\n",
|
||||
+ status);
|
||||
+ goto msg_free;
|
||||
+ }
|
||||
+
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
||||
+ "nss wds peer map success mac:%pM hw_ast_idx:%d peer_id:%d\n",
|
||||
+ wds_peer_map_msg->dest_mac, wds_peer_map_msg->ast_idx, wds_peer_map_msg->peer_id);
|
||||
+
|
||||
+msg_free:
|
||||
+ kfree(wlmsg);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int ath11k_nss_del_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
+ u8 *dest_mac)
|
||||
+{
|
||||
+ struct ath11k_base *ab = ar->ab;
|
||||
+ struct nss_wifili_wds_peer_msg *wds_peer_msg;
|
||||
+ struct nss_wifili_msg *wlmsg = NULL;
|
||||
+ nss_wifili_msg_callback_t msg_cb;
|
||||
+ nss_tx_status_t status;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC);
|
||||
+ if (wlmsg == NULL)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ wds_peer_msg = &wlmsg->msg.wdspeermsg;
|
||||
+
|
||||
+ wds_peer_msg->pdev_id = ar->pdev->pdev_id;
|
||||
+ wds_peer_msg->ast_type = ATH11K_AST_TYPE_NONE;
|
||||
+ wds_peer_msg->peer_id = peer->peer_id;
|
||||
+ ether_addr_copy(wds_peer_msg->peer_mac, peer->addr);
|
||||
+ ether_addr_copy(wds_peer_msg->dest_mac, dest_mac);
|
||||
+
|
||||
+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive;
|
||||
+
|
||||
+ nss_cmn_msg_init(&wlmsg->cm, ab->nss.if_num,
|
||||
+ NSS_WIFILI_WDS_PEER_DEL_MSG,
|
||||
+ sizeof(struct nss_wifili_wds_peer_msg),
|
||||
+ msg_cb, NULL);
|
||||
+
|
||||
+ status = nss_wifili_tx_msg(ab->nss.ctx, wlmsg);
|
||||
+ if (status != NSS_TX_SUCCESS) {
|
||||
+ ret = -EINVAL;
|
||||
+ ath11k_warn(ab, "nss send wds del peer msg tx error: %d\n",
|
||||
+ status);
|
||||
+ goto msg_free;
|
||||
+ }
|
||||
+
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
||||
+ "nss del wds peer success peer mac:%pM dest mac:%pM peer_id:%d\n",
|
||||
+ wds_peer_msg->peer_mac, wds_peer_msg->dest_mac, wds_peer_msg->peer_id);
|
||||
+
|
||||
+msg_free:
|
||||
+ kfree(wlmsg);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/*-------------------------------INIT/DEINIT---------------------------------*/
|
||||
|
||||
static int ath11k_nss_radio_buf_cfg(struct ath11k *ar, int range, int buf_sz)
|
||||
@@ -1893,7 +2319,7 @@ static int ath11k_nss_init(struct ath11k
|
||||
|
||||
status = nss_wifili_tx_msg(nss_contex, wlmsg);
|
||||
if (status != NSS_TX_SUCCESS) {
|
||||
- ath11k_warn(ab, "failure to send nss init msg\n");
|
||||
+ ath11k_warn(ab, "failure to send nss init msg: %d \n", status);
|
||||
goto unregister;
|
||||
}
|
||||
|
||||
@@ -1947,7 +2373,8 @@ static int ath11k_nss_stats_cfg(struct a
|
||||
|
||||
status = nss_wifili_tx_msg(ar->nss.ctx, wlmsg);
|
||||
if (status != NSS_TX_SUCCESS) {
|
||||
- ath11k_warn(ab, "nss stats cfg %d msg tx failure\n", nss_msg);
|
||||
+ ath11k_warn(ab, "nss stats cfg %d msg tx failure: %d\n",
|
||||
+ nss_msg, status);
|
||||
ret = -EINVAL;
|
||||
goto free;
|
||||
}
|
||||
--- a/drivers/net/wireless/ath/ath11k/nss.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/nss.h
|
||||
@@ -17,12 +17,14 @@ struct ath11k_base;
|
||||
struct ath11k_vif;
|
||||
struct ath11k_peer;
|
||||
struct ath11k_sta;
|
||||
+enum ath11k_ast_entry_type;
|
||||
struct hal_rx_mon_ppdu_info;
|
||||
struct hal_rx_user_status;
|
||||
|
||||
/* NSS DBG macro is not included as part of debug enum to avoid
|
||||
* frequent changes during upgrade*/
|
||||
-#define ATH11K_DBG_NSS 0x80000000
|
||||
+#define ATH11K_DBG_NSS 0x40000000
|
||||
+#define ATH11K_DBG_NSS_WDS 0x80000000
|
||||
|
||||
/* WIFILI Supported Target Types */
|
||||
#define ATH11K_WIFILI_TARGET_TYPE_UNKNOWN 0xFF
|
||||
@@ -205,11 +207,19 @@ int ath11k_nss_vdev_create(struct ath11k
|
||||
void ath11k_nss_vdev_delete(struct ath11k_vif *arvif);
|
||||
int ath11k_nss_vdev_up(struct ath11k_vif *arvif);
|
||||
int ath11k_nss_vdev_down(struct ath11k_vif *arvif);
|
||||
-int ath11k_nss_peer_delete(struct ath11k_base *ab, const u8 *addr);
|
||||
+int ath11k_nss_peer_delete(struct ath11k_base *ab, u32 vdev_id, const u8 *addr);
|
||||
int ath11k_nss_set_peer_authorize(struct ath11k *ar, u16 peer_id);
|
||||
-int ath11k_nss_peer_create(struct ath11k_base *ab, struct ath11k_peer *peer);
|
||||
+int ath11k_nss_peer_create(struct ath11k *ar, struct ath11k_peer *peer);
|
||||
void ath11k_nss_peer_stats_enable(struct ath11k *ar);
|
||||
void ath11k_nss_peer_stats_disable(struct ath11k *ar);
|
||||
+int ath11k_nss_add_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
+ u8 *dest_mac, enum ath11k_ast_entry_type type);
|
||||
+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);
|
||||
+int ath11k_nss_del_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
+ u8 *dest_mac);
|
||||
int ath11k_nss_set_peer_sec_type(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
struct ieee80211_key_conf *key_conf);
|
||||
void ath11k_nss_update_sta_stats(struct station_info *sinfo,
|
||||
@@ -271,12 +281,37 @@ static inline int ath11k_nss_vdev_down(s
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static inline int ath11k_nss_peer_delete(struct ath11k_base *ab, const u8 *addr)
|
||||
+static inline int ath11k_nss_peer_delete(struct ath11k_base *ab, u32 vdev_id,
|
||||
+ const u8 *addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static inline int ath11k_nss_peer_create(struct ath11k_base *ab, struct ath11k_peer *peer)
|
||||
+static inline int ath11k_nss_add_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
+ u8 *dest_mac, int type)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int ath11k_nss_update_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
+ u8 *dest_mac)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int ath11k_nss_map_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
+ u8 *dest_mac, int type)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int ath11k_nss_del_wds_peer(struct ath11k_vif *arvif, struct ath11k_peer *peer,
|
||||
+ u8 *dest_mac)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int ath11k_nss_peer_create(struct ath11k *ar, struct ath11k_peer *peer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,973 @@
|
||||
From e6ecf9e1cc115b5821a880c6dccc5d8c9cd76fbd Mon Sep 17 00:00:00 2001
|
||||
From: Sathishkumar Muruganandam <murugana@codeaurora.org>
|
||||
Date: Tue, 15 Sep 2020 21:12:37 +0530
|
||||
Subject: [PATCH] ath11k: add WDS offload support on NSS offload for STA mode
|
||||
|
||||
When 4addr is set ON for STA interface along with NSS enabled case, WDS
|
||||
offload is enabled for ethernet mode.
|
||||
|
||||
STA mode uses MEC (Multicast Echo Check) AST (Address Search Table) entry
|
||||
to update the bridge MAC address from NSS to drop the locally generated
|
||||
multicast/broadcast frames as multicast echo frames.
|
||||
|
||||
AST handling and callbacks to NSS WDS APIs are added.
|
||||
|
||||
Signed-off-by: Sathishkumar Muruganandam <murugana@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/core.h | 8 +-
|
||||
drivers/net/wireless/ath/ath11k/dp.h | 6 +-
|
||||
drivers/net/wireless/ath/ath11k/dp_rx.c | 18 +-
|
||||
drivers/net/wireless/ath/ath11k/dp_tx.c | 2 +-
|
||||
drivers/net/wireless/ath/ath11k/peer.c | 389 +++++++++++++++++++++++++++++++-
|
||||
drivers/net/wireless/ath/ath11k/peer.h | 117 ++++++++++
|
||||
drivers/net/wireless/ath/ath11k/wmi.c | 99 +++++++-
|
||||
drivers/net/wireless/ath/ath11k/wmi.h | 33 +++
|
||||
8 files changed, 658 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/core.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
||||
@@ -692,6 +692,7 @@ struct ath11k {
|
||||
struct ath11k_pdev_wmi *wmi;
|
||||
#ifdef CPTCFG_ATH11K_NSS_SUPPORT
|
||||
struct ath11k_nss nss;
|
||||
+ struct ath11k_peer *bss_peer;
|
||||
#endif
|
||||
struct ath11k_pdev_dp dp;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
@@ -1110,6 +1111,9 @@ struct ath11k_base {
|
||||
} testmode;
|
||||
#endif
|
||||
|
||||
+ u32 max_ast_index;
|
||||
+ u32 num_ast_entries;
|
||||
+
|
||||
/* must be last */
|
||||
u8 drv_priv[] __aligned(sizeof(void *));
|
||||
};
|
||||
--- a/drivers/net/wireless/ath/ath11k/dp.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/dp.h
|
||||
@@ -1111,13 +1111,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
|
||||
-#define HTT_T2H_PEER_MAP_INFO1_NEXT_HOP_M HTT_T2H_PEER_MAP_INFO2_NEXT_HOP_M
|
||||
-#define HTT_T2H_PEER_MAP_INFO1_NEXT_HOP_S HTT_T2H_PEER_MAP_INFO2_NEXT_HOP_S
|
||||
+#define HTT_T2H_PEER_UNMAP_INFO1_NEXT_HOP_M HTT_T2H_PEER_MAP_INFO2_NEXT_HOP_M
|
||||
+#define HTT_T2H_PEER_UNMAP_INFO1_NEXT_HOP_S HTT_T2H_PEER_MAP_INFO2_NEXT_HOP_S
|
||||
+#define HTT_T2H_PEER_UNMAP_INFO3_WDS_FREE_COUNT GENMASK(15, 0)
|
||||
|
||||
struct htt_t2h_peer_unmap_event {
|
||||
u32 info;
|
||||
u32 mac_addr_l32;
|
||||
u32 info1;
|
||||
+ u32 info2;
|
||||
+ u32 info3;
|
||||
} __packed;
|
||||
|
||||
struct htt_resp_msg {
|
||||
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
|
||||
@@ -1858,6 +1858,8 @@ void ath11k_dp_htt_htc_t2h_msg_handler(s
|
||||
u16 peer_mac_h16;
|
||||
u16 ast_hash;
|
||||
u16 hw_peer_id;
|
||||
+ u32 free_wds_count;
|
||||
+ bool is_wds = false;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "dp_htt rx msg type :0x%0x\n", type);
|
||||
|
||||
@@ -1893,15 +1895,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);
|
||||
- ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash,
|
||||
- hw_peer_id);
|
||||
+ is_wds = FIELD_GET(HTT_T2H_PEER_MAP_INFO2_NEXT_HOP_M,
|
||||
+ resp->peer_map_ev.info2);
|
||||
+ ath11k_peer_map_v2_event(ab, vdev_id, peer_id, mac_addr, ast_hash,
|
||||
+ hw_peer_id, is_wds);
|
||||
break;
|
||||
case HTT_T2H_MSG_TYPE_PEER_UNMAP:
|
||||
- case HTT_T2H_MSG_TYPE_PEER_UNMAP2:
|
||||
peer_id = FIELD_GET(HTT_T2H_PEER_UNMAP_INFO_PEER_ID,
|
||||
resp->peer_unmap_ev.info);
|
||||
ath11k_peer_unmap_event(ab, peer_id);
|
||||
break;
|
||||
+ case HTT_T2H_MSG_TYPE_PEER_UNMAP2:
|
||||
+ peer_id = FIELD_GET(HTT_T2H_PEER_UNMAP_INFO_PEER_ID,
|
||||
+ resp->peer_unmap_ev.info);
|
||||
+ peer_mac_h16 = FIELD_GET(HTT_T2H_PEER_UNMAP_INFO1_MAC_ADDR_H16,
|
||||
+ resp->peer_unmap_ev.info1);
|
||||
+ ath11k_dp_get_mac_addr(resp->peer_map_ev.mac_addr_l32,
|
||||
+ peer_mac_h16, mac_addr);
|
||||
+ is_wds = FIELD_GET(HTT_T2H_PEER_UNMAP_INFO1_NEXT_HOP_M,
|
||||
+ resp->peer_unmap_ev.info1);
|
||||
+ free_wds_count = FIELD_GET(HTT_T2H_PEER_UNMAP_INFO3_WDS_FREE_COUNT,
|
||||
+ resp->peer_unmap_ev.info3);
|
||||
+ ath11k_peer_unmap_v2_event(ab, peer_id, mac_addr, is_wds, free_wds_count);
|
||||
+ break;
|
||||
case HTT_T2H_MSG_TYPE_PPDU_STATS_IND:
|
||||
ath11k_htt_pull_ppdu_stats(ab, skb);
|
||||
break;
|
||||
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
|
||||
@@ -499,7 +499,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
|
||||
- * use WDS offload functionality.
|
||||
+ * use WDS offload functionality on NSS disabled case.
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
--- a/drivers/net/wireless/ath/ath11k/peer.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/peer.c
|
||||
@@ -108,6 +108,287 @@ struct ath11k_peer *ath11k_peer_find_by_
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+#ifdef CPTCFG_ATH11K_NSS_SUPPORT
|
||||
+struct ath11k_ast_entry *ath11k_peer_ast_find_by_peer(struct ath11k_base *ab,
|
||||
+ struct ath11k_peer *peer,
|
||||
+ u8* addr)
|
||||
+{
|
||||
+ struct ath11k_ast_entry *ast_entry;
|
||||
+
|
||||
+ lockdep_assert_held(&ab->base_lock);
|
||||
+
|
||||
+ list_for_each_entry(ast_entry, &peer->ast_entry_list, ase_list)
|
||||
+ if (ether_addr_equal(ast_entry->addr, addr))
|
||||
+ return ast_entry;
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+struct ath11k_ast_entry *ath11k_peer_ast_find_by_addr(struct ath11k_base *ab,
|
||||
+ u8* addr)
|
||||
+{
|
||||
+ struct ath11k_ast_entry *ast_entry;
|
||||
+ struct ath11k_peer *peer;
|
||||
+
|
||||
+ lockdep_assert_held(&ab->base_lock);
|
||||
+
|
||||
+ list_for_each_entry(peer, &ab->peers, list)
|
||||
+ list_for_each_entry(ast_entry, &peer->ast_entry_list, ase_list)
|
||||
+ if (ether_addr_equal(ast_entry->addr, addr))
|
||||
+ return ast_entry;
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+void ath11k_peer_ast_wds_wmi_wk(struct work_struct *wk)
|
||||
+{
|
||||
+ struct ath11k_ast_entry *ast_entry = container_of(wk,
|
||||
+ struct ath11k_ast_entry,
|
||||
+ wds_wmi_wk);
|
||||
+ struct ath11k *ar;
|
||||
+ struct ath11k_peer *peer;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!ast_entry)
|
||||
+ return;
|
||||
+
|
||||
+ ar = ast_entry->ar;
|
||||
+ peer = ast_entry->peer;
|
||||
+
|
||||
+ 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,
|
||||
+ ast_entry->vdev_id);
|
||||
+
|
||||
+ if (ast_entry->action == ATH11K_WDS_WMI_ADD) {
|
||||
+ ret = ath11k_wmi_send_add_update_wds_entry_cmd(ar,
|
||||
+ ast_entry->next_node_mac,
|
||||
+ ast_entry->addr,
|
||||
+ ast_entry->vdev_id,
|
||||
+ true);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ar->ab, "add wds_entry_cmd failed %d for %pM next_node %pM\n",
|
||||
+ ret, ast_entry->addr,
|
||||
+ ast_entry->next_node_mac);
|
||||
+ if (peer)
|
||||
+ ath11k_nss_del_wds_peer(ar, peer,
|
||||
+ ast_entry->addr);
|
||||
+ }
|
||||
+ } else if (ast_entry->action == ATH11K_WDS_WMI_UPDATE) {
|
||||
+ if (!peer)
|
||||
+ return;
|
||||
+
|
||||
+ ret = ath11k_wmi_send_add_update_wds_entry_cmd(ar, peer->addr,
|
||||
+ ast_entry->addr,
|
||||
+ ast_entry->vdev_id,
|
||||
+ false);
|
||||
+ if (ret)
|
||||
+ ath11k_warn(ar->ab, "update wds_entry_cmd failed %d for %pM on peer %pM\n",
|
||||
+ ret, ast_entry->addr, peer->addr);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+int ath11k_peer_add_ast(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
+ u8* mac_addr, enum ath11k_ast_entry_type type)
|
||||
+{
|
||||
+ struct ath11k_ast_entry *ast_entry = NULL;
|
||||
+ struct ath11k_base *ab = ar->ab;
|
||||
+
|
||||
+ 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);
|
||||
+ return -ENOBUFS;
|
||||
+ }
|
||||
+
|
||||
+ if (type != ATH11K_AST_TYPE_STATIC) {
|
||||
+ ast_entry = ath11k_peer_ast_find_by_addr(ab, mac_addr);
|
||||
+ if (ast_entry) {
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_MAC, "ast_entry %pM already present on peer %pM\n",
|
||||
+ mac_addr, ast_entry->peer->addr);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ast_entry = kzalloc(sizeof(*ast_entry), GFP_ATOMIC);
|
||||
+ if (!ast_entry) {
|
||||
+ ath11k_warn(ab, "failed to alloc ast_entry for %pM\n",
|
||||
+ mac_addr);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ switch (type) {
|
||||
+ case ATH11K_AST_TYPE_STATIC:
|
||||
+ peer->self_ast_entry = ast_entry;
|
||||
+ ast_entry->type = ATH11K_AST_TYPE_STATIC;
|
||||
+ break;
|
||||
+ case ATH11K_AST_TYPE_SELF:
|
||||
+ peer->self_ast_entry = ast_entry;
|
||||
+ ast_entry->type = ATH11K_AST_TYPE_SELF;
|
||||
+ break;
|
||||
+ case ATH11K_AST_TYPE_WDS:
|
||||
+ ast_entry->type = ATH11K_AST_TYPE_WDS;
|
||||
+ ast_entry->next_hop = 1;
|
||||
+ break;
|
||||
+ case ATH11K_AST_TYPE_MEC:
|
||||
+ ast_entry->type = ATH11K_AST_TYPE_MEC;
|
||||
+ ast_entry->next_hop = 1;
|
||||
+ break;
|
||||
+ default:
|
||||
+ ath11k_warn(ab, "unsupported ast_type %d", type);
|
||||
+ kfree(ast_entry);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ INIT_LIST_HEAD(&ast_entry->ase_list);
|
||||
+ INIT_WORK(&ast_entry->wds_wmi_wk, ath11k_peer_ast_wds_wmi_wk);
|
||||
+ ast_entry->vdev_id = peer->vdev_id;
|
||||
+ ast_entry->pdev_idx = peer->pdev_idx;
|
||||
+ ast_entry->is_mapped = false;
|
||||
+ ast_entry->is_active = true;
|
||||
+ ast_entry->peer = peer;
|
||||
+ ast_entry->ar = ar;
|
||||
+ ether_addr_copy(ast_entry->addr, mac_addr);
|
||||
+
|
||||
+ list_add_tail(&ast_entry->ase_list, &peer->ast_entry_list);
|
||||
+
|
||||
+ 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);
|
||||
+
|
||||
+ if (type == ATH11K_AST_TYPE_MEC)
|
||||
+ ether_addr_copy(ast_entry->next_node_mac, ar->mac_addr);
|
||||
+ else if (type == ATH11K_AST_TYPE_WDS)
|
||||
+ ether_addr_copy(ast_entry->next_node_mac, peer->addr);
|
||||
+
|
||||
+ if ((ast_entry->type == ATH11K_AST_TYPE_WDS) ||
|
||||
+ (ast_entry->type == ATH11K_AST_TYPE_MEC)) {
|
||||
+ ath11k_nss_add_wds_peer(ar, peer, mac_addr, ast_entry->type);
|
||||
+ ast_entry->action = ATH11K_WDS_WMI_ADD;
|
||||
+ ieee80211_queue_work(ar->hw, &ast_entry->wds_wmi_wk);
|
||||
+ }
|
||||
+
|
||||
+ ab->num_ast_entries++;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int ath11k_peer_update_ast(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
+ struct ath11k_ast_entry *ast_entry)
|
||||
+{
|
||||
+ struct ath11k_peer *old_peer = ast_entry->peer;
|
||||
+ struct ath11k_base *ab = ar->ab;
|
||||
+
|
||||
+ if (!ast_entry->is_mapped) {
|
||||
+ ath11k_warn(ab, "ath11k_peer_update_ast: ast_entry %pM not mapped yet\n",
|
||||
+ ast_entry->addr);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (ether_addr_equal(old_peer->addr, peer->addr) &&
|
||||
+ (ast_entry->type == ATH11K_AST_TYPE_WDS) &&
|
||||
+ (ast_entry->vdev_id == peer->vdev_id) &&
|
||||
+ (ast_entry->is_active))
|
||||
+ return 0;
|
||||
+
|
||||
+ ast_entry->vdev_id = peer->vdev_id;
|
||||
+ ast_entry->pdev_idx = peer->pdev_idx;
|
||||
+ ast_entry->type = ATH11K_AST_TYPE_WDS;
|
||||
+ ast_entry->is_active = true;
|
||||
+ ast_entry->peer = peer;
|
||||
+
|
||||
+ list_move_tail(&ast_entry->ase_list, &peer->ast_entry_list);
|
||||
+
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_MAC, "ath11k_peer_update_ast old peer %pM new peer %pM ast_entry %pM\n",
|
||||
+ old_peer->addr, peer->addr, ast_entry->addr);
|
||||
+
|
||||
+ flush_work(&ast_entry->wds_wmi_wk);
|
||||
+ ast_entry->action = ATH11K_WDS_WMI_UPDATE;
|
||||
+ ieee80211_queue_work(ar->hw, &ast_entry->wds_wmi_wk);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void ath11k_peer_map_ast(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
+ u8* mac_addr, u16 hw_peer_id, u16 ast_hash)
|
||||
+{
|
||||
+ struct ath11k_ast_entry *ast_entry = NULL;
|
||||
+ struct ath11k_base *ab = ar->ab;
|
||||
+
|
||||
+ if (!peer)
|
||||
+ return;
|
||||
+
|
||||
+ ast_entry = ath11k_peer_ast_find_by_peer(ab, peer, mac_addr);
|
||||
+
|
||||
+ if (ast_entry) {
|
||||
+ ast_entry->ast_idx = hw_peer_id;
|
||||
+ ast_entry->is_active = true;
|
||||
+ ast_entry->is_mapped = true;
|
||||
+ ast_entry->ast_hash_value = ast_hash;
|
||||
+
|
||||
+ 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_dbg(ab, ATH11K_DBG_MAC, "ath11k_peer_map_ast peer %pM ast_entry %pM\n",
|
||||
+ peer->addr, ast_entry->addr);
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
+
|
||||
+void ath11k_peer_del_ast(struct ath11k *ar, struct ath11k_ast_entry *ast_entry)
|
||||
+{
|
||||
+ struct ath11k_peer *peer;
|
||||
+ struct ath11k_base *ab = ar->ab;
|
||||
+
|
||||
+ if (!ast_entry || !ast_entry->peer)
|
||||
+ return;
|
||||
+
|
||||
+ peer = ast_entry->peer;
|
||||
+
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_MAC, "ath11k_peer_del_ast peer %pM ast_entry %pM\n",
|
||||
+ peer->addr, ast_entry->addr);
|
||||
+
|
||||
+ if (ast_entry->is_mapped)
|
||||
+ list_del(&ast_entry->ase_list);
|
||||
+
|
||||
+ /* WDS, MEC type AST entries need to be deleted on NSS */
|
||||
+ if (ast_entry->next_hop)
|
||||
+ ath11k_nss_del_wds_peer(ar, peer, ast_entry->addr);
|
||||
+
|
||||
+ cancel_work_sync(&ast_entry->wds_wmi_wk);
|
||||
+ kfree(ast_entry);
|
||||
+
|
||||
+ ab->num_ast_entries--;
|
||||
+}
|
||||
+
|
||||
+void ath11k_peer_ast_cleanup(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
+ bool is_wds, u32 free_wds_count)
|
||||
+{
|
||||
+ struct ath11k_ast_entry *ast_entry, *tmp;
|
||||
+ u32 ast_deleted_count = 0;
|
||||
+
|
||||
+ if (peer->self_ast_entry) {
|
||||
+ ath11k_peer_del_ast(ar, peer->self_ast_entry);
|
||||
+ peer->self_ast_entry = NULL;
|
||||
+ }
|
||||
+
|
||||
+ list_for_each_entry_safe(ast_entry, tmp, &peer->ast_entry_list,
|
||||
+ ase_list) {
|
||||
+ if ((ast_entry->type == ATH11K_AST_TYPE_WDS) ||
|
||||
+ (ast_entry->type == ATH11K_AST_TYPE_MEC))
|
||||
+ ast_deleted_count++;
|
||||
+ ath11k_peer_del_ast(ar, ast_entry);
|
||||
+ }
|
||||
+
|
||||
+ if (!is_wds) {
|
||||
+ if (ast_deleted_count != free_wds_count)
|
||||
+ ath11k_warn(ar->ab, "ast_deleted_count (%d) mismatch on peer %pM free_wds_count (%d)!\n",
|
||||
+ ast_deleted_count, peer->addr, free_wds_count);
|
||||
+ else
|
||||
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "ast_deleted_count (%d) on peer %pM free_wds_count (%d)\n",
|
||||
+ ast_deleted_count, peer->addr, free_wds_count);
|
||||
+ }
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id)
|
||||
{
|
||||
struct ath11k_peer *peer;
|
||||
@@ -132,11 +413,67 @@ exit:
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
}
|
||||
|
||||
+void ath11k_peer_unmap_v2_event(struct ath11k_base *ab, u16 peer_id, u8 *mac_addr,
|
||||
+ bool is_wds, u32 free_wds_count)
|
||||
+{
|
||||
+ struct ath11k_peer *peer;
|
||||
+ struct ath11k *ar;
|
||||
+
|
||||
+ spin_lock_bh(&ab->base_lock);
|
||||
+
|
||||
+ 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);
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ ar = ath11k_mac_get_ar_by_vdev_id(ab, peer->vdev_id);
|
||||
+ if (!ar) {
|
||||
+ ath11k_warn(ab, "peer-unmap-event: unknown peer vdev id %d\n",
|
||||
+ peer->vdev_id);
|
||||
+ goto free_peer;
|
||||
+ }
|
||||
+
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt peer unmap vdev %d peer %pM id %d is_wds %d free_wds_count %d\n",
|
||||
+ peer->vdev_id, peer->addr, peer_id, is_wds, free_wds_count);
|
||||
+
|
||||
+ if (ab->nss.enabled) {
|
||||
+ if (is_wds) {
|
||||
+ struct ath11k_ast_entry *ast_entry =
|
||||
+ ath11k_peer_ast_find_by_peer(ab, peer, mac_addr);
|
||||
+
|
||||
+ if (ast_entry)
|
||||
+ ath11k_peer_del_ast(ar, ast_entry);
|
||||
+ rcu_read_unlock();
|
||||
+ goto exit;
|
||||
+ } else
|
||||
+ ath11k_peer_ast_cleanup(ar, peer, is_wds, free_wds_count);
|
||||
+ }
|
||||
+
|
||||
+#ifdef CPTCFG_ATH11K_NSS_SUPPORT
|
||||
+ if (ar->bss_peer && ether_addr_equal(ar->bss_peer->addr, peer->addr))
|
||||
+ ar->bss_peer = NULL;
|
||||
+#endif
|
||||
+free_peer:
|
||||
+ rcu_read_unlock();
|
||||
+ list_del(&peer->list);
|
||||
+ kfree(peer);
|
||||
+ wake_up(&ab->peer_mapping_wq);
|
||||
+
|
||||
+exit:
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+}
|
||||
+
|
||||
void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id,
|
||||
u8 *mac_addr, u16 ast_hash, u16 hw_peer_id)
|
||||
{
|
||||
struct ath11k_peer *peer;
|
||||
+ struct ath11k *ar = NULL;
|
||||
|
||||
+ rcu_read_lock();
|
||||
+ ar = ath11k_mac_get_ar_by_vdev_id(ab, vdev_id);
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
peer = ath11k_peer_find(ab, vdev_id, mac_addr);
|
||||
if (!peer) {
|
||||
@@ -151,8 +488,8 @@ void ath11k_peer_map_event(struct ath11k
|
||||
ether_addr_copy(peer->addr, mac_addr);
|
||||
list_add(&peer->list, &ab->peers);
|
||||
wake_up(&ab->peer_mapping_wq);
|
||||
- if (ab->nss.enabled)
|
||||
- ath11k_nss_peer_create(ab, peer);
|
||||
+ if (ab->nss.enabled && ar)
|
||||
+ ath11k_nss_peer_create(ar, peer);
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "peer map vdev %d peer %pM id %d\n",
|
||||
@@ -160,6 +497,69 @@ void ath11k_peer_map_event(struct ath11k
|
||||
|
||||
exit:
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
+ rcu_read_unlock();
|
||||
+}
|
||||
+
|
||||
+void ath11k_peer_map_v2_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id,
|
||||
+ u8 *mac_addr, u16 ast_hash, u16 hw_peer_id,
|
||||
+ bool is_wds)
|
||||
+{
|
||||
+ struct ath11k_peer *peer;
|
||||
+ struct ath11k *ar = NULL;
|
||||
+ int ret;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ ar = ath11k_mac_get_ar_by_vdev_id(ab, vdev_id);
|
||||
+ spin_lock_bh(&ab->base_lock);
|
||||
+ peer = ath11k_peer_find(ab, vdev_id, mac_addr);
|
||||
+ if (!peer && !is_wds) {
|
||||
+ peer = kzalloc(sizeof(*peer), GFP_ATOMIC);
|
||||
+ if (!peer) {
|
||||
+ ath11k_warn(ab, "failed to allocated peer for %pM vdev_id %d\n",
|
||||
+ mac_addr, vdev_id);
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ peer->vdev_id = vdev_id;
|
||||
+ peer->peer_id = peer_id;
|
||||
+ peer->ast_hash = ast_hash;
|
||||
+ peer->hw_peer_id = hw_peer_id;
|
||||
+ ether_addr_copy(peer->addr, mac_addr);
|
||||
+ list_add(&peer->list, &ab->peers);
|
||||
+#ifdef CPTCFG_ATH11K_NSS_SUPPORT
|
||||
+ INIT_LIST_HEAD(&peer->ast_entry_list);
|
||||
+#endif
|
||||
+ if (ab->nss.enabled && ar) {
|
||||
+ ret = ath11k_nss_peer_create(ar, peer);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ab, "failed to do nss peer create: %d\n",
|
||||
+ ret);
|
||||
+ goto peer_free;
|
||||
+ }
|
||||
+ }
|
||||
+ wake_up(&ab->peer_mapping_wq);
|
||||
+ }
|
||||
+
|
||||
+ if (is_wds)
|
||||
+ peer = ath11k_peer_find_by_id(ab, peer_id);
|
||||
+
|
||||
+ if (ab->nss.enabled && ar)
|
||||
+ ath11k_peer_map_ast(ar, peer, mac_addr, hw_peer_id, ast_hash);
|
||||
+
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt peer map vdev %d peer %pM id %d is_wds %d\n",
|
||||
+ vdev_id, mac_addr, peer_id, is_wds);
|
||||
+
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+ goto exit;
|
||||
+
|
||||
+peer_free:
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+ mutex_lock(&ar->conf_mutex);
|
||||
+ ath11k_peer_delete(ar, vdev_id, mac_addr);
|
||||
+ mutex_unlock(&ar->conf_mutex);
|
||||
+exit:
|
||||
+ rcu_read_unlock();
|
||||
}
|
||||
|
||||
static int ath11k_wait_for_peer_common(struct ath11k_base *ab, int vdev_id,
|
||||
@@ -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
|
||||
|
||||
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) {
|
||||
if (peer->vdev_id != vdev_id)
|
||||
continue;
|
||||
|
||||
ath11k_warn(ab, "removing stale peer %pM from vdev_id %d\n",
|
||||
peer->addr, vdev_id);
|
||||
|
||||
+#ifdef CPTCFG_ATH11K_NSS_SUPPORT
|
||||
+ if (peer->self_ast_entry) {
|
||||
+ ath11k_peer_del_ast(ar, peer->self_ast_entry);
|
||||
+ peer->self_ast_entry = NULL;
|
||||
+ }
|
||||
+
|
||||
+ list_for_each_entry_safe(ast_entry, tmp_ast,
|
||||
+ &peer->ast_entry_list, ase_list)
|
||||
+ ath11k_peer_del_ast(ar, ast_entry);
|
||||
+#endif
|
||||
+
|
||||
ath11k_peer_rhash_delete(ab, peer);
|
||||
list_del(&peer->list);
|
||||
kfree(peer);
|
||||
@@ -316,7 +730,7 @@ static int __ath11k_peer_delete(struct a
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
reinit_completion(&ar->peer_delete_done);
|
||||
- ath11k_nss_peer_delete(ar->ab, addr);
|
||||
+ ath11k_nss_peer_delete(ar->ab, vdev_id, addr);
|
||||
|
||||
mutex_lock(&ab->tbl_mtx_lock);
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
@@ -391,6 +805,7 @@ int ath11k_peer_create(struct ath11k *ar
|
||||
struct ieee80211_sta *sta, struct peer_create_params *param)
|
||||
{
|
||||
struct ath11k_peer *peer;
|
||||
+ struct ieee80211_vif *vif = arvif->vif;
|
||||
struct ath11k_sta *arsta;
|
||||
int ret, fbret;
|
||||
|
||||
@@ -466,6 +881,13 @@ int ath11k_peer_create(struct ath11k *ar
|
||||
peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN;
|
||||
peer->vif = arvif->vif;
|
||||
|
||||
+#ifdef CPTCFG_ATH11K_NSS_SUPPORT
|
||||
+ if (vif->type == NL80211_IFTYPE_STATION && ar->ab->nss.enabled)
|
||||
+ ar->bss_peer = peer;
|
||||
+ else
|
||||
+ ar->bss_peer = NULL;
|
||||
+#endif
|
||||
+
|
||||
if (sta) {
|
||||
arsta = ath11k_sta_to_arsta(sta);
|
||||
arsta->tcl_metadata |= FIELD_PREP(HTT_TCL_META_DATA_TYPE, 0) |
|
||||
--- a/drivers/net/wireless/ath/ath11k/peer.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/peer.h
|
||||
@@ -18,6 +18,47 @@ struct ppdu_user_delayba {
|
||||
u32 resp_rate_flags;
|
||||
};
|
||||
|
||||
+enum ath11k_ast_entry_type {
|
||||
+ ATH11K_AST_TYPE_NONE, /* static ast entry for connected peer */
|
||||
+ ATH11K_AST_TYPE_STATIC, /* static ast entry for connected peer */
|
||||
+ ATH11K_AST_TYPE_SELF, /* static ast entry for self peer (STA mode) */
|
||||
+ ATH11K_AST_TYPE_WDS, /* WDS peer ast entry type*/
|
||||
+ ATH11K_AST_TYPE_MEC, /* Multicast echo ast entry type */
|
||||
+ ATH11K_AST_TYPE_WDS_HM, /* HM WDS entry */
|
||||
+ ATH11K_AST_TYPE_STA_BSS, /* BSS entry(STA mode) */
|
||||
+ ATH11K_AST_TYPE_DA, /* AST entry based on Destination address */
|
||||
+ ATH11K_AST_TYPE_WDS_HM_SEC, /* HM WDS entry for secondary radio */
|
||||
+ ATH11K_AST_TYPE_MAX
|
||||
+};
|
||||
+
|
||||
+enum ath11k_wds_wmi_action {
|
||||
+ ATH11K_WDS_WMI_ADD = 1,
|
||||
+ ATH11K_WDS_WMI_UPDATE,
|
||||
+
|
||||
+ ATH11K_WDS_WMI_MAX
|
||||
+};
|
||||
+
|
||||
+struct ath11k_ast_entry {
|
||||
+ u16 ast_idx;
|
||||
+ u8 addr[ETH_ALEN];
|
||||
+ u8 next_node_mac[ETH_ALEN];
|
||||
+ enum ath11k_wds_wmi_action action;
|
||||
+ struct work_struct wds_wmi_wk;
|
||||
+ struct ath11k_peer *peer;
|
||||
+ struct ath11k *ar;
|
||||
+ bool next_hop;
|
||||
+ bool is_active;
|
||||
+ bool is_mapped;
|
||||
+ u8 pdev_idx;
|
||||
+ u8 vdev_id;
|
||||
+ u16 ast_hash_value;
|
||||
+ int ref_cnt;
|
||||
+ enum ath11k_ast_entry_type type;
|
||||
+ bool delete_in_progress;
|
||||
+ void *cookie;
|
||||
+ struct list_head ase_list;
|
||||
+};
|
||||
+
|
||||
struct ath11k_peer {
|
||||
struct list_head list;
|
||||
struct ieee80211_sta *sta;
|
||||
@@ -29,6 +70,10 @@ struct ath11k_peer {
|
||||
u8 pdev_idx;
|
||||
u16 hw_peer_id;
|
||||
struct ath11k_nss_peer nss;
|
||||
+#ifdef CPTCFG_ATH11K_NSS_SUPPORT
|
||||
+ struct ath11k_ast_entry *self_ast_entry;
|
||||
+ struct list_head ast_entry_list;
|
||||
+#endif
|
||||
|
||||
/* protected by ab->data_lock */
|
||||
struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
|
||||
@@ -54,8 +99,13 @@ struct ath11k_peer {
|
||||
};
|
||||
|
||||
void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id);
|
||||
+void ath11k_peer_unmap_v2_event(struct ath11k_base *ab, u16 peer_id, u8 *mac_addr,
|
||||
+ bool is_wds, u32 free_wds_count);
|
||||
void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id,
|
||||
u8 *mac_addr, u16 ast_hash, u16 hw_peer_id);
|
||||
+void ath11k_peer_map_v2_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id,
|
||||
+ u8 *mac_addr, u16 ast_hash, u16 hw_peer_id,
|
||||
+ bool is_wds);
|
||||
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,
|
||||
@@ -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);
|
||||
+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,
|
||||
+ struct ath11k_ast_entry *ast_entry);
|
||||
+void ath11k_peer_map_ast(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
+ u8* mac_addr, u16 hw_peer_id, u16 ast_hash);
|
||||
+void ath11k_peer_del_ast(struct ath11k *ar, struct ath11k_ast_entry *ast_entry);
|
||||
+void ath11k_peer_ast_cleanup(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
+ bool is_wds, u32 free_wds_count);
|
||||
+void ath11k_peer_ast_wds_wmi_wk(struct work_struct *wk);
|
||||
+struct ath11k_ast_entry *ath11k_peer_ast_find_by_peer(struct ath11k_base *ab,
|
||||
+ struct ath11k_peer *peer,
|
||||
+ u8* addr);
|
||||
+#else
|
||||
+static inline struct ath11k_ast_entry *ath11k_peer_ast_find_by_addr(struct ath11k_base *ab,
|
||||
+ u8* addr)
|
||||
+{
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static inline int ath11k_peer_add_ast(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
+ u8* mac_addr, enum ath11k_ast_entry_type type)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int ath11k_peer_update_ast(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
+ struct ath11k_ast_entry *ast_entry)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline void ath11k_peer_map_ast(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
+ u8* mac_addr, u16 hw_peer_id, u16 ast_hash)
|
||||
+{
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static inline void ath11k_peer_del_ast(struct ath11k *ar,
|
||||
+ struct ath11k_ast_entry *ast_entry)
|
||||
+{
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static inline void ath11k_peer_ast_cleanup(struct ath11k *ar,
|
||||
+ struct ath11k_peer *peer,
|
||||
+ bool is_wds, u32 free_wds_count)
|
||||
+{
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static inline void ath11k_peer_ast_wds_wmi_wk(struct work_struct *wk)
|
||||
+{
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static inline struct ath11k_ast_entry *ath11k_peer_ast_find_by_peer(struct ath11k_base *ab,
|
||||
+ struct ath11k_peer *peer,
|
||||
+ u8* addr)
|
||||
+{
|
||||
+ 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
|
||||
@@ -161,6 +161,8 @@ static const struct wmi_tlv_policy wmi_t
|
||||
.min_len = sizeof(struct ath11k_wmi_p2p_noa_info) },
|
||||
[WMI_TAG_P2P_NOA_EVENT] = {
|
||||
.min_len = sizeof(struct wmi_p2p_noa_event) },
|
||||
+ [WMI_TAG_WDS_ADDR_EVENT] = {
|
||||
+ .min_len = sizeof(struct wmi_wds_addr_event) },
|
||||
};
|
||||
|
||||
#define PRIMAP(_hw_mode_) \
|
||||
@@ -1133,6 +1135,51 @@ int ath11k_wmi_send_peer_delete_cmd(stru
|
||||
return ret;
|
||||
}
|
||||
|
||||
+int ath11k_wmi_send_add_update_wds_entry_cmd(struct ath11k *ar,
|
||||
+ const u8 *peer_addr,
|
||||
+ const u8 *wds_addr, u8 vdev_id,
|
||||
+ bool add_wds)
|
||||
+{
|
||||
+ struct ath11k_pdev_wmi *wmi = ar->wmi;
|
||||
+ struct wmi_add_wds_entry_cmd *cmd;
|
||||
+ struct sk_buff *skb;
|
||||
+ int ret;
|
||||
+
|
||||
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
|
||||
+ if (!skb)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ cmd = (struct wmi_add_wds_entry_cmd *)skb->data;
|
||||
+ if (add_wds)
|
||||
+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_PEER_ADD_WDS_ENTRY_CMD) |
|
||||
+ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
|
||||
+ else
|
||||
+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_PEER_UPDATE_WDS_ENTRY_CMD) |
|
||||
+ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
|
||||
+
|
||||
+ ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
|
||||
+ ether_addr_copy(cmd->wds_macaddr.addr, wds_addr);
|
||||
+ cmd->vdev_id = vdev_id;
|
||||
+ cmd->flags = WMI_WDS_FLAG_STATIC;
|
||||
+
|
||||
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
||||
+ "WMI add WDS entry vdev_id %d peer_addr %pM, wds_addr %pM flags %x\n",
|
||||
+ vdev_id, peer_addr, wds_addr, cmd->flags);
|
||||
+
|
||||
+ if (add_wds)
|
||||
+ ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PEER_ADD_WDS_ENTRY_CMDID);
|
||||
+ else
|
||||
+ ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PEER_UPDATE_WDS_ENTRY_CMDID);
|
||||
+
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ar->ab, "failed to send WMI_PEER_%s_WDS_ENTRY cmd\n",
|
||||
+ add_wds ? "ADD" : "UPDATE");
|
||||
+ dev_kfree_skb(skb);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
int ath11k_wmi_send_pdev_set_regdomain(struct ath11k *ar,
|
||||
struct pdev_set_regdomain_params *param)
|
||||
{
|
||||
@@ -6483,6 +6530,36 @@ static int ath11k_pull_peer_assoc_conf_e
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int ath11k_pull_wds_addr_ev(struct ath11k_base *ab, struct sk_buff *skb,
|
||||
+ struct wmi_wds_addr_arg *wds_addr_arg)
|
||||
+{
|
||||
+ const void **tb;
|
||||
+ const struct wmi_wds_addr_event *ev;
|
||||
+ int ret;
|
||||
+
|
||||
+ tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
+ if (IS_ERR(tb)) {
|
||||
+ ret = PTR_ERR(tb);
|
||||
+ ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ev = tb[WMI_TAG_WDS_ADDR_EVENT];
|
||||
+ if (!ev) {
|
||||
+ ath11k_warn(ab, "failed to fetch wds peer ev");
|
||||
+ kfree(tb);
|
||||
+ return -EPROTO;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(wds_addr_arg->event_type, ev->event_type, WMI_NUM_WDS_EVENTS);
|
||||
+ wds_addr_arg->vdev_id = ev->vdev_id;
|
||||
+ wds_addr_arg->peer_macaddr = ev->peer_macaddr.addr;
|
||||
+ wds_addr_arg->dst_macaddr = ev->dst_macaddr.addr;
|
||||
+
|
||||
+ kfree(tb);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void ath11k_wmi_pull_pdev_stats_base(const struct wmi_pdev_stats_base *src,
|
||||
struct ath11k_fw_stats_pdev *dst)
|
||||
{
|
||||
@@ -7307,6 +7384,7 @@ static int ath11k_wmi_tlv_rdy_parse(stru
|
||||
|
||||
ether_addr_copy(ab->mac_addr,
|
||||
fixed_param.ready_event_min.mac_addr.addr);
|
||||
+ ab->max_ast_index = fixed_param.max_ast_index + 1;
|
||||
ab->pktlog_defs_checksum = fixed_param.pktlog_defs_checksum;
|
||||
break;
|
||||
case WMI_TAG_ARRAY_FIXED_STRUCT:
|
||||
@@ -8879,6 +8957,22 @@ exit:
|
||||
kfree(tb);
|
||||
}
|
||||
|
||||
+static void ath11k_wmi_wds_peer_event(struct ath11k_base *ab,
|
||||
+ struct sk_buff *skb)
|
||||
+{
|
||||
+ struct wmi_wds_addr_arg wds_addr_arg = {0};
|
||||
+
|
||||
+ if (ath11k_pull_wds_addr_ev(ab, skb, &wds_addr_arg) != 0) {
|
||||
+ ath11k_warn(ab, "failed to extract wds addr event");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
+ "wds addr event vdev id %d peer macaddr %pM dst macaddr %pM\n",
|
||||
+ wds_addr_arg.vdev_id, wds_addr_arg.peer_macaddr,
|
||||
+ wds_addr_arg.dst_macaddr);
|
||||
+}
|
||||
+
|
||||
static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_cmd_hdr *cmd_hdr;
|
||||
@@ -9012,6 +9106,9 @@ static void ath11k_wmi_tlv_op_rx(struct
|
||||
case WMI_P2P_NOA_EVENTID:
|
||||
ath11k_wmi_p2p_noa_event(ab, skb);
|
||||
break;
|
||||
+ case WMI_WDS_PEER_EVENTID:
|
||||
+ ath11k_wmi_wds_peer_event(ab, skb);
|
||||
+ break;
|
||||
default:
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "unsupported event id 0x%x\n", id);
|
||||
break;
|
||||
--- a/drivers/net/wireless/ath/ath11k/wmi.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
|
||||
@@ -3028,6 +3028,21 @@ struct wmi_peer_delete_cmd {
|
||||
struct wmi_mac_addr peer_macaddr;
|
||||
} __packed;
|
||||
|
||||
+#define WMI_WDS_FLAG_STATIC 0x1 /* Disable aging & learning */
|
||||
+struct wmi_add_wds_entry_cmd {
|
||||
+ u32 tlv_header;
|
||||
+ struct wmi_mac_addr peer_macaddr;
|
||||
+ struct wmi_mac_addr wds_macaddr;
|
||||
+ u32 flags;
|
||||
+ u32 vdev_id;
|
||||
+} __packed;
|
||||
+
|
||||
+struct wmi_remove_wds_entry_cmd {
|
||||
+ u32 tlv_header;
|
||||
+ struct wmi_mac_addr wds_macaddr;
|
||||
+ u32 vdev_id;
|
||||
+} __packed;
|
||||
+
|
||||
struct wmi_peer_reorder_queue_setup_cmd {
|
||||
u32 tlv_header;
|
||||
u32 vdev_id;
|
||||
@@ -4641,6 +4656,21 @@ struct wmi_probe_resp_tx_status_event {
|
||||
u32 tx_status;
|
||||
} __packed;
|
||||
|
||||
+#define WMI_NUM_WDS_EVENTS 4
|
||||
+struct wmi_wds_addr_arg {
|
||||
+ u32 event_type[WMI_NUM_WDS_EVENTS];
|
||||
+ const u8 *peer_macaddr;
|
||||
+ const u8 *dst_macaddr;
|
||||
+ u32 vdev_id;
|
||||
+};
|
||||
+
|
||||
+struct wmi_wds_addr_event {
|
||||
+ u32 event_type[WMI_NUM_WDS_EVENTS];
|
||||
+ struct wmi_mac_addr peer_macaddr;
|
||||
+ struct wmi_mac_addr dst_macaddr;
|
||||
+ u32 vdev_id;
|
||||
+} __packed;
|
||||
+
|
||||
/*
|
||||
* PDEV statistics
|
||||
*/
|
||||
@@ -6440,6 +6470,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);
|
||||
+int ath11k_wmi_send_add_update_wds_entry_cmd(struct ath11k *ar,
|
||||
+ const u8 *peer_addr, const u8 *wds_addr,
|
||||
+ u8 vdev_id, bool add_wds);
|
||||
int ath11k_wmi_vdev_delete(struct ath11k *ar, u8 vdev_id);
|
||||
void ath11k_wmi_start_scan_init(struct ath11k *ar, struct scan_req_params *arg);
|
||||
int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar,
|
||||
@ -0,0 +1,392 @@
|
||||
From 0e29b669153f100b60107d5f6b3fe407b71ba79a Mon Sep 17 00:00:00 2001
|
||||
From: Sowmiya Sree Elavalagan <ssreeela@codeaurora.org>
|
||||
Date: Wed, 30 Sep 2020 22:33:42 +0530
|
||||
Subject: [PATCH] ath11k: QOS null frame tx over wmi
|
||||
|
||||
Added support to send qos null frame through FW.
|
||||
NSS driver does not support QOS null frame tx.
|
||||
Hence this is brought for nss offload case to send
|
||||
qos null frame. QOS null packet queued from mac80211
|
||||
is sent to FW through wmi interface. This happens only if FW supports
|
||||
qos null tx, this is based on service bit received in ext2 service
|
||||
event from FW. On successful transmission of QOS null frame status
|
||||
is set 0 in the event received for this wmi message. This is status
|
||||
is sent to mac80211 for further handling.
|
||||
|
||||
Signed-off-by: Sowmiya Sree Elavalagan <ssreeela@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/mac.c | 28 ++++-
|
||||
drivers/net/wireless/ath/ath11k/wmi.c | 200 ++++++++++++++++++++++++++--------
|
||||
drivers/net/wireless/ath/ath11k/wmi.h | 46 +++++++-
|
||||
3 files changed, 220 insertions(+), 54 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
||||
@@ -6015,6 +6015,16 @@ static int ath11k_mac_mgmt_tx_wmi(struct
|
||||
|
||||
ATH11K_SKB_CB(skb)->paddr = paddr;
|
||||
|
||||
+ if (ieee80211_is_qos_nullfunc(hdr->frame_control)) {
|
||||
+ ret = ath11k_wmi_qos_null_send(ar, arvif->vdev_id, buf_id, skb);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ar->ab, "failed to send qos null frame over wmi: %d\n", ret);
|
||||
+ goto err_unmap_buf;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
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);
|
||||
@@ -6082,8 +6092,8 @@ static void ath11k_mgmt_over_wmi_tx_work
|
||||
}
|
||||
}
|
||||
|
||||
-static int ath11k_mac_mgmt_tx(struct ath11k *ar, struct sk_buff *skb,
|
||||
- bool is_prb_rsp)
|
||||
+static int ath11k_mac_tx_over_wmi(struct ath11k *ar, struct sk_buff *skb,
|
||||
+ bool is_prb_rsp)
|
||||
{
|
||||
struct sk_buff_head *q = &ar->wmi_mgmt_tx_queue;
|
||||
|
||||
@@ -6145,7 +6155,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);
|
||||
- ret = ath11k_mac_mgmt_tx(ar, skb, is_prb_rsp);
|
||||
+ ret = ath11k_mac_tx_over_wmi(ar, skb, is_prb_rsp);
|
||||
if (ret) {
|
||||
if (ret != -EBUSY)
|
||||
ath11k_warn(ar->ab, "failed to queue management frame %d\n",
|
||||
@@ -6160,6 +6170,20 @@ static void ath11k_mac_op_tx(struct ieee
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
return;
|
||||
+ } else if (ar->ab->nss.enabled &&
|
||||
+ ieee80211_is_qos_nullfunc(hdr->frame_control) &&
|
||||
+ test_bit(WMI_TLV_SERVICE_QOS_NULL_FRAME_TX_OVER_WMI,
|
||||
+ ar->ab->wmi_ab.svc_map)) {
|
||||
+ /* NSS driver does not support tx qos null pkt hence it is offload
|
||||
+ * to fw via wmi path similar to mgmt frames
|
||||
+ */
|
||||
+ ret = ath11k_mac_tx_over_wmi(ar, skb, false);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ar->ab, "failed to queue qos null frame %d\n",
|
||||
+ ret);
|
||||
+ ieee80211_free_txskb(ar->hw, skb);
|
||||
+ }
|
||||
+ return;
|
||||
}
|
||||
|
||||
if (control->sta)
|
||||
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
@@ -118,7 +118,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]
|
||||
- = { .min_len = sizeof(struct wmi_mgmt_tx_compl_event) },
|
||||
+ = { .min_len = sizeof(struct wmi_tx_compl_event) },
|
||||
[WMI_TAG_SCAN_EVENT]
|
||||
= { .min_len = sizeof(struct wmi_scan_event) },
|
||||
[WMI_TAG_PEER_STA_KICKOUT_EVENT]
|
||||
@@ -708,6 +708,55 @@ int ath11k_wmi_mgmt_send(struct ath11k *
|
||||
return ret;
|
||||
}
|
||||
|
||||
+int ath11k_wmi_qos_null_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
|
||||
+ struct sk_buff *frame)
|
||||
+{
|
||||
+ struct ath11k_pdev_wmi *wmi = ar->wmi;
|
||||
+ struct wmi_qos_null_tx_cmd *cmd;
|
||||
+ struct wmi_tlv *frame_tlv;
|
||||
+ struct sk_buff *skb;
|
||||
+ u32 buf_len;
|
||||
+ int len, ret = 0;
|
||||
+
|
||||
+ buf_len = frame->len < WMI_QOS_NULL_SEND_BUF_LEN ?
|
||||
+ frame->len : WMI_QOS_NULL_SEND_BUF_LEN;
|
||||
+
|
||||
+ len = sizeof(*cmd) + sizeof(*frame_tlv) + roundup(buf_len, 4);
|
||||
+
|
||||
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
|
||||
+ if (!skb)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ cmd = (struct wmi_qos_null_tx_cmd *)skb->data;
|
||||
+ cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_QOS_NULL_FRAME_TX_SEND) |
|
||||
+ FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
|
||||
+ cmd->vdev_id = vdev_id;
|
||||
+ cmd->desc_id = buf_id;
|
||||
+ cmd->paddr_lo = lower_32_bits(ATH11K_SKB_CB(frame)->paddr);
|
||||
+ cmd->paddr_hi = upper_32_bits(ATH11K_SKB_CB(frame)->paddr);
|
||||
+ cmd->frame_len = frame->len;
|
||||
+ cmd->buf_len = buf_len;
|
||||
+
|
||||
+ frame_tlv = (struct wmi_tlv *)(skb->data + sizeof(*cmd));
|
||||
+ frame_tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) |
|
||||
+ FIELD_PREP(WMI_TLV_LEN, buf_len);
|
||||
+
|
||||
+ memcpy(frame_tlv->value, frame->data, buf_len);
|
||||
+
|
||||
+ ath11k_ce_byte_swap(frame_tlv->value, buf_len);
|
||||
+
|
||||
+ ret = ath11k_wmi_cmd_send(wmi, skb, WMI_QOS_NULL_FRAME_TX_SEND_CMDID);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ar->ab,
|
||||
+ "failed to submit WMI_QOS_NULL_FRAME_TX_SEND_CMDID cmd\n");
|
||||
+ dev_kfree_skb(skb);
|
||||
+ }
|
||||
+
|
||||
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
||||
+ "wmi QOS null tx send cmd sent successfully\n");
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
int ath11k_wmi_vdev_create(struct ath11k *ar, u8 *macaddr,
|
||||
struct vdev_create_params *param)
|
||||
{
|
||||
@@ -6025,8 +6074,8 @@ static int ath11k_pull_mgmt_rx_params_tl
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int wmi_process_mgmt_tx_comp(struct ath11k *ar,
|
||||
- struct wmi_mgmt_tx_compl_event *tx_compl_param)
|
||||
+static int wmi_process_tx_comp(struct ath11k *ar,
|
||||
+ struct wmi_tx_compl_event *tx_compl_param)
|
||||
{
|
||||
struct sk_buff *msdu;
|
||||
struct ieee80211_tx_info *info;
|
||||
@@ -6064,6 +6113,11 @@ static int wmi_process_mgmt_tx_comp(stru
|
||||
info->status.ack_signal = tx_compl_param->ack_rssi;
|
||||
}
|
||||
|
||||
+ /* dont update rates in this path, qos null data tx completions also can
|
||||
+ * take this path in case of nss offload and can update invalid rates.
|
||||
+ */
|
||||
+ info->status.rates[0].idx = -1;
|
||||
+
|
||||
hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
frm_type = FIELD_GET(IEEE80211_FCTL_STYPE, hdr->frame_control);
|
||||
|
||||
@@ -6082,10 +6136,13 @@ static int wmi_process_mgmt_tx_comp(stru
|
||||
arvif = ath11k_vif_to_arvif(vif);
|
||||
mgmt_stats = &arvif->mgmt_stats;
|
||||
|
||||
- if (!tx_compl_param->status)
|
||||
- mgmt_stats->tx_compl_succ[frm_type]++;
|
||||
- else
|
||||
- mgmt_stats->tx_compl_fail[frm_type]++;
|
||||
+ if (ieee80211_is_mgmt(hdr->frame_control)) {
|
||||
+ if (!tx_compl_param->status)
|
||||
+ mgmt_stats->tx_compl_succ[frm_type]++;
|
||||
+ else
|
||||
+ mgmt_stats->tx_compl_fail[frm_type]++;
|
||||
+ }
|
||||
+
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
skip_mgmt_stats:
|
||||
@@ -6107,12 +6164,13 @@ skip_mgmt_stats:
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int ath11k_pull_mgmt_tx_compl_param_tlv(struct ath11k_base *ab,
|
||||
- struct sk_buff *skb,
|
||||
- struct wmi_mgmt_tx_compl_event *param)
|
||||
+static int ath11k_pull_tx_compl_param_tlv(struct ath11k_base *ab,
|
||||
+ struct sk_buff *skb,
|
||||
+ struct wmi_tx_compl_event *param,
|
||||
+ int event_id)
|
||||
{
|
||||
const void **tb;
|
||||
- const struct wmi_mgmt_tx_compl_event *ev;
|
||||
+ const struct wmi_tx_compl_event *ev;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
|
||||
@@ -6122,7 +6180,7 @@ static int ath11k_pull_mgmt_tx_compl_par
|
||||
return ret;
|
||||
}
|
||||
|
||||
- ev = tb[WMI_TAG_MGMT_TX_COMPL_EVENT];
|
||||
+ ev = tb[event_id];
|
||||
if (!ev) {
|
||||
ath11k_warn(ab, "failed to fetch mgmt tx compl ev");
|
||||
kfree(tb);
|
||||
@@ -7840,10 +7898,11 @@ exit:
|
||||
|
||||
static void ath11k_mgmt_tx_compl_event(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
- struct wmi_mgmt_tx_compl_event tx_compl_param = {0};
|
||||
+ struct wmi_tx_compl_event tx_compl_param = {0};
|
||||
struct ath11k *ar;
|
||||
|
||||
- if (ath11k_pull_mgmt_tx_compl_param_tlv(ab, skb, &tx_compl_param) != 0) {
|
||||
+ if (ath11k_pull_tx_compl_param_tlv(ab, skb, &tx_compl_param,
|
||||
+ WMI_TAG_MGMT_TX_COMPL_EVENT) != 0) {
|
||||
ath11k_warn(ab, "failed to extract mgmt tx compl event");
|
||||
return;
|
||||
}
|
||||
@@ -7856,7 +7915,7 @@ static void ath11k_mgmt_tx_compl_event(s
|
||||
goto exit;
|
||||
}
|
||||
|
||||
- wmi_process_mgmt_tx_comp(ar, &tx_compl_param);
|
||||
+ wmi_process_tx_comp(ar, &tx_compl_param);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_MGMT,
|
||||
"event mgmt tx compl ev pdev_id %d, desc_id %d, status %d ack_rssi %d",
|
||||
@@ -7867,6 +7926,36 @@ exit:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
+static void ath11k_qos_null_compl_event(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
+{
|
||||
+ struct wmi_tx_compl_event tx_compl_param = {0};
|
||||
+ struct ath11k *ar;
|
||||
+
|
||||
+ if (ath11k_pull_tx_compl_param_tlv(ab, skb, &tx_compl_param,
|
||||
+ WMI_TAG_QOS_NULL_FRAME_TX_STATUS) != 0) {
|
||||
+ ath11k_warn(ab, "failed to extract qos null tx compl event");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ ar = ath11k_mac_get_ar_by_pdev_id(ab, tx_compl_param.pdev_id);
|
||||
+ if (!ar) {
|
||||
+ ath11k_warn(ab, "invalid pdev id %d in qos_null_tx_compl_event\n",
|
||||
+ tx_compl_param.pdev_id);
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ wmi_process_tx_comp(ar, &tx_compl_param);
|
||||
+
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_WMI,
|
||||
+ "QOS null tx compl ev pdev_id %d, desc_id %d, status %d",
|
||||
+ tx_compl_param.pdev_id, tx_compl_param.desc_id,
|
||||
+ tx_compl_param.status);
|
||||
+
|
||||
+exit:
|
||||
+ rcu_read_unlock();
|
||||
+}
|
||||
+
|
||||
static struct ath11k *ath11k_get_ar_on_scan_state(struct ath11k_base *ab,
|
||||
u32 vdev_id,
|
||||
enum ath11k_scan_state state)
|
||||
@@ -9109,6 +9198,10 @@ static void ath11k_wmi_tlv_op_rx(struct
|
||||
case WMI_WDS_PEER_EVENTID:
|
||||
ath11k_wmi_wds_peer_event(ab, skb);
|
||||
break;
|
||||
+ case WMI_QOS_NULL_FRAME_TX_COMPLETION_EVENTID:
|
||||
+ ath11k_qos_null_compl_event(ab, skb);
|
||||
+ break;
|
||||
+
|
||||
default:
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "unsupported event id 0x%x\n", id);
|
||||
break;
|
||||
--- a/drivers/net/wireless/ath/ath11k/wmi.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
|
||||
@@ -376,6 +376,7 @@ 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_ADDBA_CLEAR_RESP_CMDID = WMI_TLV_CMD(WMI_GRP_BA_NEG),
|
||||
WMI_ADDBA_SEND_CMDID,
|
||||
WMI_ADDBA_STATUS_CMDID,
|
||||
@@ -706,6 +707,8 @@ enum wmi_tlv_event_id {
|
||||
WMI_TBTTOFFSET_EXT_UPDATE_EVENTID,
|
||||
WMI_OFFCHAN_DATA_TX_COMPLETION_EVENTID,
|
||||
WMI_HOST_FILS_DISCOVERY_EVENTID,
|
||||
+ WMI_HOST_SWBA_V2_EVENTID,
|
||||
+ WMI_QOS_NULL_FRAME_TX_COMPLETION_EVENTID,
|
||||
WMI_TX_DELBA_COMPLETE_EVENTID = WMI_TLV_CMD(WMI_GRP_BA_NEG),
|
||||
WMI_TX_ADDBA_COMPLETE_EVENTID,
|
||||
WMI_BA_RSP_SSN_EVENTID,
|
||||
@@ -1895,6 +1898,9 @@ enum wmi_tlv_tag {
|
||||
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,
|
||||
+ /* TODO add all the missing cmds */
|
||||
+ WMI_TAG_QOS_NULL_FRAME_TX_SEND = 0x3A6,
|
||||
+ WMI_TAG_QOS_NULL_FRAME_TX_STATUS,
|
||||
WMI_TAG_VDEV_SET_TPC_POWER_CMD = 0x3B5,
|
||||
WMI_TAG_VDEV_CH_POWER_INFO,
|
||||
WMI_TAG_PDEV_SET_BIOS_SAR_TABLE_CMD = 0x3D8,
|
||||
@@ -2126,7 +2132,17 @@ enum wmi_tlv_service {
|
||||
WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT = 246,
|
||||
WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249,
|
||||
WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253,
|
||||
+ WMI_TLV_SERVICE_CONFIGURE_ROAM_TRIGGER_PARAM_SUPPORT = 254,
|
||||
+ WMI_TLV_SERVICE_CFR_TA_RA_AS_FP_SUPPORT = 255,
|
||||
+ WMI_TLV_SERVICE_CFR_CAPTURE_COUNT_SUPPORT = 256,
|
||||
+ WMI_TLV_SERVICE_OCV_SUPPORT = 257,
|
||||
+ WMI_TLV_SERVICE_LL_STATS_PER_CHAN_RX_TX_TIME_SUPPORT = 258,
|
||||
+ WMI_TLV_SERVICE_THERMAL_MULTI_CLIENT_SUPPORT = 259,
|
||||
+ WMI_TLV_SERVICE_NAN_SEND_NAN_ENABLE_RESPONSE_TO_HOST = 260,
|
||||
+ WMI_TLV_SERVICE_UNIFIED_LL_GET_STA_CMD_SUPPORT = 261,
|
||||
+ 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,
|
||||
|
||||
/* The second 128 bits */
|
||||
WMI_MAX_EXT_SERVICE = 256,
|
||||
@@ -3883,6 +3899,7 @@ struct wmi_scan_prob_req_oui_cmd {
|
||||
} __packed;
|
||||
|
||||
#define WMI_MGMT_SEND_DOWNLD_LEN 64
|
||||
+#define WMI_QOS_NULL_SEND_BUF_LEN 64
|
||||
|
||||
#define WMI_TX_PARAMS_DWORD0_POWER GENMASK(7, 0)
|
||||
#define WMI_TX_PARAMS_DWORD0_MCS_MASK GENMASK(19, 8)
|
||||
@@ -3893,9 +3910,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)
|
||||
-#define WMI_TX_PARAMS_DWORD1_RSVD GENMASK(31, 21)
|
||||
+#define WMI_TX_PARAMS_DWORD1_CFR_CAPTURE BIT(21)
|
||||
+#define WMI_TX_PARAMS_DWORD1_RSVD GENMASK(31, 22)
|
||||
|
||||
-struct wmi_mgmt_send_params {
|
||||
+struct wmi_tx_send_params {
|
||||
u32 tlv_header;
|
||||
u32 tx_params_dword0;
|
||||
u32 tx_params_dword1;
|
||||
@@ -4987,7 +5005,7 @@ struct wmi_rssi_ctl_ext {
|
||||
u32 rssi_ctl_ext[MAX_ANTENNA_EIGHT - ATH_MAX_ANTENNA];
|
||||
};
|
||||
|
||||
-struct wmi_mgmt_tx_compl_event {
|
||||
+struct wmi_tx_compl_event {
|
||||
u32 desc_id;
|
||||
u32 status;
|
||||
u32 pdev_id;
|
||||
@@ -5819,6 +5837,17 @@ struct wmi_debug_log_config_cmd_fixed_pa
|
||||
u32 value;
|
||||
} __packed;
|
||||
|
||||
+struct wmi_qos_null_tx_cmd {
|
||||
+ u32 tlv_header;
|
||||
+ u32 vdev_id;
|
||||
+ u32 desc_id;
|
||||
+ u32 paddr_lo;
|
||||
+ u32 paddr_hi;
|
||||
+ u32 frame_len;
|
||||
+ u32 buf_len;
|
||||
+ u32 tx_params_valid;
|
||||
+} __packed;
|
||||
+
|
||||
#define MAX_RADIOS 3
|
||||
|
||||
#define WMI_SERVICE_READY_TIMEOUT_HZ (5 * HZ)
|
||||
@@ -6428,6 +6457,8 @@ int ath11k_wmi_mgmt_send(struct ath11k *
|
||||
struct sk_buff *frame);
|
||||
int ath11k_wmi_p2p_go_bcn_ie(struct ath11k *ar, u32 vdev_id,
|
||||
const u8 *p2p_ie);
|
||||
+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,
|
||||
struct ieee80211_mutable_offsets *offs,
|
||||
struct sk_buff *bcn, u32 ema_param);
|
||||
@ -0,0 +1,784 @@
|
||||
From 83c2a029a5300b2aaeaa9855011668b407d142c2 Mon Sep 17 00:00:00 2001
|
||||
From: Sathishkumar Muruganandam <murugana@codeaurora.org>
|
||||
Date: Fri, 20 Nov 2020 11:41:11 +0530
|
||||
Subject: [PATCH 2/3] ath11k: add support for ext vdev in NSS for AP_VLAN vif
|
||||
handling
|
||||
|
||||
- add ext vdev NSS API callbacks required for AP_VLAN vif
|
||||
- invoke ieee80211_rx_nss_notify_4addr on WDS Rx path for 4addr frames until
|
||||
ext vdev interface is UP
|
||||
- do ext vdev down of all AP_VLAN vifs upon vdev down of associated AP vif
|
||||
|
||||
Signed-off-by: Sathishkumar Muruganandam <murugana@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/nss.c | 452 ++++++++++++++++++++++++++++++++--
|
||||
drivers/net/wireless/ath/ath11k/nss.h | 57 +++++
|
||||
2 files changed, 495 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/nss.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/nss.c
|
||||
@@ -323,6 +323,10 @@ void ath11k_nss_wifili_event_receive(str
|
||||
ath11k_dbg(ab, ATH11K_DBG_NSS_WDS, "nss wifili wds peer del event received %d response %d error %d\n",
|
||||
msg_type, response, error);
|
||||
break;
|
||||
+ case NSS_WIFILI_PEER_4ADDR_EVENT_MSG:
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS, "nss wifili peer 4addr event received %d response %d error %d\n",
|
||||
+ msg_type, response, error);
|
||||
+ break;
|
||||
default:
|
||||
ath11k_dbg(ab, ATH11K_DBG_NSS, "unhandled event %d\n", msg_type);
|
||||
break;
|
||||
@@ -556,8 +560,9 @@ static int ath11k_nss_undecap_nwifi(stru
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void ath11k_nss_wds_type_rx(struct ath11k *ar, u8* src_mac, u8 is_sa_valid,
|
||||
- u8 addr4_valid, u16 peer_id)
|
||||
+static void ath11k_nss_wds_type_rx(struct ath11k *ar, struct net_device *dev,
|
||||
+ u8* src_mac, u8 is_sa_valid, u8 addr4_valid,
|
||||
+ u16 peer_id, bool *drop)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ath11k_ast_entry *ast_entry = NULL;
|
||||
@@ -579,19 +584,22 @@ static void ath11k_nss_wds_type_rx(struc
|
||||
if (!is_sa_valid) {
|
||||
ath11k_peer_add_ast(ar, ta_peer, src_mac,
|
||||
ATH11K_AST_TYPE_WDS);
|
||||
- ath11k_nss_add_wds_peer(ar, ta_peer,
|
||||
- src_mac, ATH11K_AST_TYPE_WDS);
|
||||
+ if (!ta_peer->nss.ext_vdev_up)
|
||||
+ ieee80211_rx_nss_notify_4addr(dev, ta_peer->addr);
|
||||
} else {
|
||||
if (!ast_entry) {
|
||||
ath11k_peer_add_ast(ar, ta_peer, src_mac,
|
||||
ATH11K_AST_TYPE_WDS);
|
||||
- ath11k_nss_add_wds_peer(ar, ta_peer, src_mac,
|
||||
- ATH11K_AST_TYPE_WDS);
|
||||
- } else {
|
||||
+ if (!ta_peer->nss.ext_vdev_up)
|
||||
+ ieee80211_rx_nss_notify_4addr(dev, ta_peer->addr);
|
||||
+ } else if (ast_entry->type == ATH11K_AST_TYPE_WDS) {
|
||||
ath11k_peer_update_ast(ar, ta_peer, ast_entry);
|
||||
ath11k_nss_update_wds_peer(ar, ta_peer, src_mac);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ if (!ta_peer->nss.ext_vdev_up)
|
||||
+ *drop = true;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
@@ -635,7 +643,8 @@ static void ath11k_nss_mec_handler(struc
|
||||
|
||||
static void ath11k_nss_vdev_spl_receive_ext_wdsdata(struct ath11k_vif *arvif,
|
||||
struct sk_buff *skb,
|
||||
- struct nss_wifi_vdev_wds_per_packet_metadata *wds_metadata)
|
||||
+ struct nss_wifi_vdev_wds_per_packet_metadata *wds_metadata,
|
||||
+ bool *drop)
|
||||
{
|
||||
struct ath11k *ar = arvif->ar;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
@@ -656,8 +665,8 @@ static void ath11k_nss_vdev_spl_receive_
|
||||
|
||||
switch (wds_type) {
|
||||
case NSS_WIFI_VDEV_WDS_TYPE_RX:
|
||||
- ath11k_nss_wds_type_rx(ar, src_mac, is_sa_valid,
|
||||
- addr4_valid, peer_id);
|
||||
+ ath11k_nss_wds_type_rx(ar, skb->dev, src_mac, is_sa_valid,
|
||||
+ addr4_valid, peer_id, drop);
|
||||
break;
|
||||
case NSS_WIFI_VDEV_WDS_TYPE_MEC:
|
||||
ath11k_nss_mec_handler(ar, (u8 *)(skb->data));
|
||||
@@ -724,6 +733,7 @@ ath11k_nss_vdev_special_data_receive(str
|
||||
struct ieee80211_vif *vif;
|
||||
struct ath11k_vif *arvif;
|
||||
struct ath11k_base *ab;
|
||||
+ bool drop = false;
|
||||
bool eth_decap = false;
|
||||
int data_offs = 0;
|
||||
int ret = 0;
|
||||
@@ -779,10 +789,11 @@ ath11k_nss_vdev_special_data_receive(str
|
||||
NSS_WIFI_VDEV_EXT_DATA_PKT_TYPE_WDS_LEARN) {
|
||||
wds_metadata = &wifi_metadata->metadata.wds_metadata;
|
||||
ath11k_nss_vdev_spl_receive_ext_wdsdata(arvif, skb,
|
||||
- wds_metadata);
|
||||
+ wds_metadata, &drop);
|
||||
}
|
||||
|
||||
- ath11k_nss_deliver_rx(arvif->vif, skb, eth_decap, data_offs, napi);
|
||||
+ if (!drop)
|
||||
+ ath11k_nss_deliver_rx(arvif->vif, skb, eth_decap, data_offs, napi);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -845,6 +856,68 @@ ath11k_nss_vdev_data_receive(struct net_
|
||||
ath11k_nss_deliver_rx(arvif->vif, skb, eth_decap, data_offs, napi);
|
||||
}
|
||||
|
||||
+static void
|
||||
+ath11k_nss_ext_vdev_special_data_receive(struct net_device *dev,
|
||||
+ struct sk_buff *skb,
|
||||
+ __attribute__((unused)) struct napi_struct *napi)
|
||||
+{
|
||||
+ dev_kfree_skb_any(skb);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+ath11k_nss_ext_vdev_data_receive(struct net_device *dev, struct sk_buff *skb,
|
||||
+ __attribute__((unused)) struct napi_struct *napi)
|
||||
+{
|
||||
+ struct wireless_dev *wdev;
|
||||
+ struct ieee80211_vif *vif;
|
||||
+ struct ath11k_vif *arvif;
|
||||
+ struct ath11k_base *ab;
|
||||
+ bool eth_decap = false;
|
||||
+ int data_offs = 0;
|
||||
+ int ret;
|
||||
+
|
||||
+ 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);
|
||||
+}
|
||||
+
|
||||
int ath11k_nss_tx(struct ath11k_vif *arvif, struct sk_buff *skb)
|
||||
{
|
||||
struct ath11k *ar = arvif->ar;
|
||||
@@ -869,10 +942,16 @@ int ath11k_nss_tx(struct ath11k_vif *arv
|
||||
ath11k_nss_tx_encap_nwifi(skb);
|
||||
|
||||
send:
|
||||
- ath11k_dbg_dump(ar->ab, ATH11K_DBG_DP_TX, "", "nss tx msdu: ",
|
||||
- skb->data, skb->len);
|
||||
-
|
||||
- status = nss_wifi_vdev_tx_buf(arvif->ar->nss.ctx, skb, arvif->nss.if_num);
|
||||
+ ath11k_dbg_dump(ar->ab, ATH11K_DBG_DP_TX,
|
||||
+ arvif->vif->type == NL80211_IFTYPE_AP_VLAN ? "ext vdev" : "",
|
||||
+ "nss tx msdu: ", skb->data, skb->len);
|
||||
+
|
||||
+ if (arvif->vif->type == NL80211_IFTYPE_AP_VLAN)
|
||||
+ status = nss_wifi_ext_vdev_tx_buf(arvif->nss.ctx, skb,
|
||||
+ arvif->nss.if_num);
|
||||
+ else
|
||||
+ status = nss_wifi_vdev_tx_buf(arvif->ar->nss.ctx, skb,
|
||||
+ arvif->nss.if_num);
|
||||
|
||||
if (status != NSS_TX_SUCCESS) {
|
||||
ath11k_dbg(ar->ab, (ATH11K_DBG_NSS | ATH11K_DBG_DP_TX),
|
||||
@@ -1214,6 +1293,7 @@ int ath11k_nss_vdev_up(struct ath11k_vif
|
||||
struct nss_wifi_vdev_msg *vdev_msg = NULL;
|
||||
struct nss_wifi_vdev_enable_msg *vdev_en;
|
||||
struct ath11k *ar = arvif->ar;
|
||||
+ struct ath11k_vif *ap_vlan_arvif, *tmp;
|
||||
nss_tx_status_t status;
|
||||
int ret = 0;
|
||||
|
||||
@@ -1245,6 +1325,12 @@ int ath11k_nss_vdev_up(struct ath11k_vif
|
||||
}
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_NSS, "nss vdev up tx msg success\n");
|
||||
+
|
||||
+ if (arvif->vif->type == NL80211_IFTYPE_AP)
|
||||
+ list_for_each_entry_safe(ap_vlan_arvif, tmp,
|
||||
+ &arvif->ap_vlan_arvifs, list)
|
||||
+ if (ap_vlan_arvif->nss.added)
|
||||
+ ath11k_nss_ext_vdev_up(ap_vlan_arvif);
|
||||
free:
|
||||
kfree(vdev_msg);
|
||||
return ret;
|
||||
@@ -1254,6 +1340,7 @@ int ath11k_nss_vdev_down(struct ath11k_v
|
||||
{
|
||||
struct nss_wifi_vdev_msg *vdev_msg = NULL;
|
||||
struct ath11k *ar = arvif->ar;
|
||||
+ struct ath11k_vif *ap_vlan_arvif, *tmp;
|
||||
nss_tx_status_t status;
|
||||
int ret = 0;
|
||||
|
||||
@@ -1281,11 +1368,362 @@ int ath11k_nss_vdev_down(struct ath11k_v
|
||||
}
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_NSS, "nss vdev down tx msg success\n");
|
||||
+
|
||||
+ if (arvif->vif->type == NL80211_IFTYPE_AP)
|
||||
+ list_for_each_entry_safe(ap_vlan_arvif, tmp,
|
||||
+ &arvif->ap_vlan_arvifs, list)
|
||||
+ ath11k_nss_ext_vdev_down(ap_vlan_arvif);
|
||||
free:
|
||||
kfree(vdev_msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+int ath11k_nss_ext_vdev_cfg_wds_peer(struct ath11k_vif *arvif,
|
||||
+ u8 *wds_addr, u32 wds_peer_id)
|
||||
+{
|
||||
+ struct ath11k *ar = arvif->ar;
|
||||
+ struct nss_wifi_ext_vdev_msg *ext_vdev_msg = NULL;
|
||||
+ struct nss_wifi_ext_vdev_wds_msg *cfg_wds_msg = NULL;
|
||||
+ nss_tx_status_t status;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (arvif->vif->type != NL80211_IFTYPE_AP_VLAN)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ ext_vdev_msg = kzalloc(sizeof(struct nss_wifi_ext_vdev_msg), GFP_ATOMIC);
|
||||
+ if (!ext_vdev_msg)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ cfg_wds_msg = &ext_vdev_msg->msg.wmsg;
|
||||
+ cfg_wds_msg->wds_peer_id = wds_peer_id;
|
||||
+ ether_addr_copy((u8 *)cfg_wds_msg->mac_addr, wds_addr);
|
||||
+
|
||||
+ nss_wifi_ext_vdev_msg_init(ext_vdev_msg, arvif->nss.if_num,
|
||||
+ NSS_WIFI_EXT_VDEV_MSG_CONFIGURE_WDS,
|
||||
+ sizeof(struct nss_wifi_ext_vdev_wds_msg),
|
||||
+ NULL, arvif);
|
||||
+
|
||||
+ status = nss_wifi_ext_vdev_tx_msg_sync(arvif->nss.ctx, ext_vdev_msg);
|
||||
+ if (status != NSS_TX_SUCCESS) {
|
||||
+ ath11k_warn(ar->ab, "failed to configure wds peer nss_err:%d\n",
|
||||
+ status);
|
||||
+ ret = -EINVAL;
|
||||
+ goto free;
|
||||
+ }
|
||||
+
|
||||
+ ret = 0;
|
||||
+free:
|
||||
+ kfree(ext_vdev_msg);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int ath11k_nss_ext_vdev_wds_4addr_allow(struct ath11k_vif *arvif,
|
||||
+ u32 wds_peer_id)
|
||||
+{
|
||||
+ struct ath11k *ar = arvif->ar;
|
||||
+ struct nss_wifili_peer_wds_4addr_allow_msg *cfg_4addr_msg = NULL;
|
||||
+ nss_wifili_msg_callback_t msg_cb;
|
||||
+ struct nss_wifili_msg *wlmsg;
|
||||
+ nss_tx_status_t status;
|
||||
+
|
||||
+ if (arvif->vif->type != NL80211_IFTYPE_AP_VLAN)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC);
|
||||
+ if (!wlmsg)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ cfg_4addr_msg = &wlmsg->msg.wpswm;
|
||||
+ cfg_4addr_msg->peer_id = wds_peer_id;
|
||||
+ cfg_4addr_msg->if_num = arvif->nss.if_num;
|
||||
+ cfg_4addr_msg->enable = true;
|
||||
+
|
||||
+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive;
|
||||
+
|
||||
+ nss_cmn_msg_init(&wlmsg->cm, ar->ab->nss.if_num,
|
||||
+ NSS_WIFILI_PEER_4ADDR_EVENT_MSG,
|
||||
+ sizeof(struct nss_wifili_peer_wds_4addr_allow_msg),
|
||||
+ msg_cb, NULL);
|
||||
+
|
||||
+ status = nss_wifili_tx_msg(ar->nss.ctx, wlmsg);
|
||||
+ if (status != NSS_TX_SUCCESS) {
|
||||
+ ath11k_warn(ar->ab, "nss wds 4addr allow if_num %d, peer_id %d cfg fail: %d\n",
|
||||
+ arvif->nss.if_num, wds_peer_id, status);
|
||||
+ goto free;
|
||||
+ }
|
||||
+
|
||||
+ ath11k_dbg(ar->ab, ATH11K_DBG_NSS_WDS, "nss wds 4addr allow if_num %d, peer_id %d cfg complete\n",
|
||||
+ arvif->nss.if_num, wds_peer_id);
|
||||
+free:
|
||||
+ kfree(wlmsg);
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
+int ath11k_nss_ext_vdev_configure(struct ath11k_vif *arvif)
|
||||
+{
|
||||
+ struct ath11k *ar = arvif->ar;
|
||||
+ struct ath11k_vif *ap_vif = arvif->nss.ap_vif;
|
||||
+ struct nss_wifi_ext_vdev_msg *ext_vdev_msg = NULL;
|
||||
+ struct nss_wifi_ext_vdev_configure_if_msg *ext_vdev_cfg = NULL;
|
||||
+ nss_tx_status_t status;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (arvif->vif->type != NL80211_IFTYPE_AP_VLAN)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ ext_vdev_msg = kzalloc(sizeof(struct nss_wifi_ext_vdev_msg), GFP_ATOMIC);
|
||||
+ if (!ext_vdev_msg)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ext_vdev_cfg = &ext_vdev_msg->msg.cmsg;
|
||||
+
|
||||
+ ext_vdev_cfg->radio_ifnum = ar->nss.if_num;
|
||||
+ ext_vdev_cfg->pvap_ifnum = ap_vif->nss.if_num;
|
||||
+
|
||||
+ ether_addr_copy(ext_vdev_cfg->mac_addr, arvif->vif->addr);
|
||||
+
|
||||
+ nss_wifi_ext_vdev_msg_init(ext_vdev_msg, arvif->nss.if_num,
|
||||
+ NSS_WIFI_EXT_VDEV_MSG_CONFIGURE_IF,
|
||||
+ sizeof(struct nss_wifi_ext_vdev_configure_if_msg),
|
||||
+ NULL, arvif);
|
||||
+
|
||||
+ status = nss_wifi_ext_vdev_tx_msg_sync(arvif->ar->nss.ctx, ext_vdev_msg);
|
||||
+ if (status != NSS_TX_SUCCESS) {
|
||||
+ ath11k_warn(ar->ab, "failed to configure nss ext vdev nss_err:%d\n",
|
||||
+ status);
|
||||
+ ret = -EINVAL;
|
||||
+ goto free;
|
||||
+ }
|
||||
+
|
||||
+ ret = 0;
|
||||
+free:
|
||||
+ kfree(ext_vdev_msg);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+void ath11k_nss_ext_vdev_unregister(struct ath11k_vif *arvif)
|
||||
+{
|
||||
+ struct ath11k_base *ab = arvif->ar->ab;
|
||||
+
|
||||
+ if (arvif->vif->type != NL80211_IFTYPE_AP_VLAN)
|
||||
+ return;
|
||||
+
|
||||
+ nss_wifi_ext_vdev_unregister_if(arvif->nss.if_num);
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS, "unregistered nss vdev %d \n",
|
||||
+ arvif->nss.if_num);
|
||||
+}
|
||||
+
|
||||
+static int ath11k_nss_ext_vdev_register(struct ath11k_vif *arvif,
|
||||
+ struct net_device *netdev)
|
||||
+{
|
||||
+ struct ath11k *ar = arvif->ar;
|
||||
+ struct ath11k_base *ab = ar->ab;
|
||||
+ nss_tx_status_t status;
|
||||
+ enum nss_dynamic_interface_type di_type;
|
||||
+ u32 features = 0;
|
||||
+
|
||||
+ if (arvif->vif->type != NL80211_IFTYPE_AP_VLAN || arvif->nss.ctx)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ di_type = NSS_DYNAMIC_INTERFACE_TYPE_WIFI_EXT_VDEV_WDS;
|
||||
+
|
||||
+ arvif->nss.ctx = nss_wifi_ext_vdev_register_if(arvif->nss.if_num,
|
||||
+ ath11k_nss_ext_vdev_data_receive,
|
||||
+ ath11k_nss_ext_vdev_special_data_receive,
|
||||
+ NULL, netdev, features,
|
||||
+ arvif);
|
||||
+
|
||||
+ if (!arvif->nss.ctx) {
|
||||
+ ath11k_warn(ab, "failed to register nss vdev if_num %d nss_err:%d\n",
|
||||
+ arvif->nss.if_num, status);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS, "registered nss ext vdev if_num %d\n",
|
||||
+ arvif->nss.if_num);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void ath11k_nss_ext_vdev_free(struct ath11k_vif *arvif)
|
||||
+{
|
||||
+ struct ath11k_base *ab = arvif->ar->ab;
|
||||
+ nss_tx_status_t status;
|
||||
+
|
||||
+ if (arvif->vif->type != NL80211_IFTYPE_AP_VLAN)
|
||||
+ return;
|
||||
+
|
||||
+ status = nss_dynamic_interface_dealloc_node(
|
||||
+ arvif->nss.if_num,
|
||||
+ NSS_DYNAMIC_INTERFACE_TYPE_WIFI_EXT_VDEV_WDS);
|
||||
+ if (status != NSS_TX_SUCCESS)
|
||||
+ ath11k_warn(ab, "failed to free nss ext vdev err:%d\n",
|
||||
+ status);
|
||||
+ else
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
||||
+ "nss ext vdev interface deallocated\n");
|
||||
+}
|
||||
+
|
||||
+static int ath11k_nss_ext_vdev_alloc(struct ath11k_vif *arvif)
|
||||
+{
|
||||
+ struct ath11k_base *ab = arvif->ar->ab;
|
||||
+ enum nss_dynamic_interface_type di_type;
|
||||
+ int if_num;
|
||||
+
|
||||
+ di_type = NSS_DYNAMIC_INTERFACE_TYPE_WIFI_EXT_VDEV_WDS;
|
||||
+
|
||||
+ if_num = nss_dynamic_interface_alloc_node(di_type);
|
||||
+ if (if_num < 0) {
|
||||
+ ath11k_warn(ab, "failed to allocate nss ext vdev\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ arvif->nss.if_num = if_num;
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
||||
+ "nss ext vdev interface %pM allocated if_num %d\n",
|
||||
+ arvif->vif->addr, if_num);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int ath11k_nss_ext_vdev_create(struct ath11k_vif *arvif)
|
||||
+{
|
||||
+ struct ath11k *ar = arvif->ar;
|
||||
+ struct ath11k_base *ab = ar->ab;
|
||||
+ struct wireless_dev *wdev;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!ab->nss.enabled)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (arvif->nss.created)
|
||||
+ return 0;
|
||||
+
|
||||
+ wdev = ieee80211_vif_to_wdev_relaxed(arvif->vif);
|
||||
+ if (!wdev) {
|
||||
+ ath11k_warn(ab, "ath11k_nss: ext wdev is null\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (!wdev->netdev) {
|
||||
+ ath11k_warn(ab, "ath11k_nss: ext netdev is null\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ ret = ath11k_nss_ext_vdev_alloc(arvif);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = ath11k_nss_ext_vdev_register(arvif, wdev->netdev);
|
||||
+ if (ret)
|
||||
+ goto free_ext_vdev;
|
||||
+
|
||||
+ arvif->nss.created = true;
|
||||
+
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
||||
+ "nss ext vdev interface created ctx %pK, ifnum %d\n",
|
||||
+ arvif->nss.ctx, arvif->nss.if_num);
|
||||
+
|
||||
+ return ret;
|
||||
+
|
||||
+free_ext_vdev:
|
||||
+ ath11k_nss_ext_vdev_free(arvif);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+void ath11k_nss_ext_vdev_delete(struct ath11k_vif *arvif)
|
||||
+{
|
||||
+ if (!arvif->ar->ab->nss.enabled)
|
||||
+ return;
|
||||
+
|
||||
+ if (!arvif->nss.created)
|
||||
+ return;
|
||||
+
|
||||
+ ath11k_dbg(arvif->ar->ab, ATH11K_DBG_NSS_WDS,
|
||||
+ "nss ext vdev interface delete ctx %pK, ifnum %d\n",
|
||||
+ arvif->nss.ctx, arvif->nss.if_num);
|
||||
+
|
||||
+ ath11k_nss_ext_vdev_unregister(arvif);
|
||||
+
|
||||
+ ath11k_nss_ext_vdev_free(arvif);
|
||||
+
|
||||
+ arvif->nss.created = false;
|
||||
+}
|
||||
+
|
||||
+int ath11k_nss_ext_vdev_up(struct ath11k_vif *arvif)
|
||||
+{
|
||||
+ struct nss_wifi_ext_vdev_msg *ext_vdev_msg = NULL;
|
||||
+ struct ath11k *ar = arvif->ar;
|
||||
+ nss_tx_status_t status;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ if (!ar->ab->nss.enabled)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (arvif->vif->type != NL80211_IFTYPE_AP_VLAN)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (arvif->nss.ext_vdev_up)
|
||||
+ return 0;
|
||||
+
|
||||
+ ext_vdev_msg = kzalloc(sizeof(struct nss_wifi_vdev_msg), GFP_ATOMIC);
|
||||
+ if (!ext_vdev_msg)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ nss_wifi_ext_vdev_msg_init(ext_vdev_msg, arvif->nss.if_num, NSS_IF_OPEN,
|
||||
+ sizeof(struct nss_if_open), NULL, arvif);
|
||||
+
|
||||
+ status = nss_wifi_ext_vdev_tx_msg_sync(arvif->nss.ctx, ext_vdev_msg);
|
||||
+ if (status != NSS_TX_SUCCESS) {
|
||||
+ ath11k_warn(ar->ab, "nss ext vdev up tx msg error %d\n", status);
|
||||
+ ret = -EINVAL;
|
||||
+ goto free;
|
||||
+ }
|
||||
+
|
||||
+ ath11k_dbg(ar->ab, ATH11K_DBG_NSS_WDS, "nss ext vdev up tx msg success\n");
|
||||
+ arvif->nss.ext_vdev_up = true;
|
||||
+free:
|
||||
+ kfree(ext_vdev_msg);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int ath11k_nss_ext_vdev_down(struct ath11k_vif *arvif)
|
||||
+{
|
||||
+ struct nss_wifi_ext_vdev_msg *ext_vdev_msg = NULL;
|
||||
+ struct ath11k *ar = arvif->ar;
|
||||
+ nss_tx_status_t status;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ if (!ar->ab->nss.enabled)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (arvif->vif->type != NL80211_IFTYPE_AP_VLAN)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ ext_vdev_msg = kzalloc(sizeof(struct nss_wifi_ext_vdev_msg), GFP_ATOMIC);
|
||||
+ if (!ext_vdev_msg)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ nss_wifi_ext_vdev_msg_init(ext_vdev_msg, arvif->nss.if_num, NSS_IF_CLOSE,
|
||||
+ sizeof(struct nss_if_close), NULL, arvif);
|
||||
+
|
||||
+ status = nss_wifi_ext_vdev_tx_msg_sync(arvif->nss.ctx, ext_vdev_msg);
|
||||
+ if (status != NSS_TX_SUCCESS) {
|
||||
+ ath11k_warn(ar->ab, "nss ext vdev down tx msg error %d\n", status);
|
||||
+ ret = -EINVAL;
|
||||
+ goto free;
|
||||
+ }
|
||||
+
|
||||
+ ath11k_dbg(ar->ab, ATH11K_DBG_NSS_WDS, "nss ext vdev down tx msg success\n");
|
||||
+
|
||||
+ arvif->nss.ext_vdev_up = false;
|
||||
+free:
|
||||
+ kfree(ext_vdev_msg);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/*----------------------------Peer Setup/Config -----------------------------*/
|
||||
|
||||
int ath11k_nss_set_peer_sec_type(struct ath11k *ar,
|
||||
@@ -1379,22 +1817,22 @@ free:
|
||||
return status;
|
||||
}
|
||||
|
||||
-void ath11k_nss_update_sta_stats(struct station_info *sinfo,
|
||||
- struct ieee80211_sta *sta,
|
||||
- struct ath11k_sta *arsta)
|
||||
+void ath11k_nss_update_sta_stats(struct ath11k_vif *arvif,
|
||||
+ struct station_info *sinfo,
|
||||
+ struct ieee80211_sta *sta)
|
||||
{
|
||||
struct sta_info *stainfo;
|
||||
struct ath11k_peer *peer;
|
||||
- struct ath11k *ar = arsta->arvif->ar;
|
||||
+ struct ath11k *ar = arvif->ar;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
|
||||
- if (!ab->nss.enabled)
|
||||
+ if (!ab->nss.stats_enabled)
|
||||
return;
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
- peer = ath11k_peer_find_by_addr(arsta->arvif->ar->ab, sta->addr);
|
||||
+ peer = ath11k_peer_find_by_addr(ab, sta->addr);
|
||||
if (!peer) {
|
||||
- ath11k_dbg(ab, ATH11K_DBG_NSS, "unable to find peer %pM\n",
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_NSS, "sta stats: unable to find peer %pM\n",
|
||||
sta->addr);
|
||||
goto exit;
|
||||
}
|
||||
@@ -1466,13 +1904,13 @@ void ath11k_nss_update_sta_rxrate(struct
|
||||
struct ath11k_peer *peer,
|
||||
struct hal_rx_user_status *user_stats)
|
||||
{
|
||||
- struct ath11k_sta *arsta = (struct ath11k_sta *)peer->sta->drv_priv;
|
||||
u16 ath11k_hal_rx_legacy_rates[] =
|
||||
{ 10, 20, 55, 60, 90, 110, 120, 180, 240, 360, 480, 540 };
|
||||
u16 rate = 0;
|
||||
u32 preamble_type;
|
||||
u8 mcs, nss;
|
||||
- struct ath11k *ar = arsta->arvif->ar;
|
||||
+ struct ath11k_vif *arvif = ath11k_vif_to_arvif(peer->vif);
|
||||
+ struct ath11k *ar = arvif->ar;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
|
||||
if (!ab->nss.enabled)
|
||||
@@ -1776,8 +2214,8 @@ int ath11k_nss_add_wds_peer(struct ath11
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
||||
- "nss add wds peer success peer mac:%pM dest mac:%pM peer_id:%d\n",
|
||||
- wds_peer_msg->peer_mac, wds_peer_msg->dest_mac, wds_peer_msg->peer_id);
|
||||
+ "nss add wds peer success pdev:%d peer mac:%pM dest mac:%pM peer_id:%d\n",
|
||||
+ wds_peer_msg->pdev_id, wds_peer_msg->peer_mac, wds_peer_msg->dest_mac, wds_peer_msg->peer_id);
|
||||
|
||||
msg_free:
|
||||
kfree(wlmsg);
|
||||
@@ -1822,8 +2260,8 @@ int ath11k_nss_update_wds_peer(struct at
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
||||
- "nss update wds peer success peer mac:%pM dest mac:%pM peer_id:%d\n",
|
||||
- wds_peer_msg->peer_mac, wds_peer_msg->dest_mac, wds_peer_msg->peer_id);
|
||||
+ "nss update wds peer success pdev:%d peer mac:%pM dest mac:%pM peer_id:%d\n",
|
||||
+ wds_peer_msg->pdev_id, wds_peer_msg->peer_mac, wds_peer_msg->dest_mac, wds_peer_msg->peer_id);
|
||||
|
||||
msg_free:
|
||||
kfree(wlmsg);
|
||||
--- a/drivers/net/wireless/ath/ath11k/nss.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/nss.h
|
||||
@@ -151,6 +151,7 @@ enum ath11k_nss_peer_sec_type {
|
||||
struct ath11k_nss_peer {
|
||||
uint32_t *vaddr;
|
||||
dma_addr_t paddr;
|
||||
+ bool ext_vdev_up;
|
||||
struct peer_stats *nss_stats;
|
||||
struct completion complete;
|
||||
};
|
||||
@@ -165,6 +166,16 @@ struct arvif_nss {
|
||||
int encap;
|
||||
/* Keep the copy of decap type for nss */
|
||||
int decap;
|
||||
+ /* AP_VLAN vif context obtained on ext vdev register */
|
||||
+ void* ctx;
|
||||
+ /* Parent AP vif stored in case of AP_VLAN vif */
|
||||
+ struct ath11k_vif *ap_vif;
|
||||
+ /* Flag to notify if vlan arvif object is added to arvif list*/
|
||||
+ bool added;
|
||||
+ /* Flag to notify if ext vdev is up/down */
|
||||
+ bool ext_vdev_up;
|
||||
+ /* WDS cfg should be done only once for ext vdev */
|
||||
+ bool wds_cfg_done;
|
||||
bool created;
|
||||
};
|
||||
|
||||
@@ -220,11 +231,21 @@ int ath11k_nss_map_wds_peer(struct ath11
|
||||
u8 *dest_mac, enum ath11k_ast_entry_type type);
|
||||
int ath11k_nss_del_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
u8 *dest_mac);
|
||||
+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,
|
||||
+ u32 wds_peer_id);
|
||||
+int ath11k_nss_ext_vdev_create(struct ath11k_vif *arvif);
|
||||
+int ath11k_nss_ext_vdev_configure(struct ath11k_vif *arvif);
|
||||
+void ath11k_nss_ext_vdev_unregister(struct ath11k_vif *arvif);
|
||||
+int ath11k_nss_ext_vdev_up(struct ath11k_vif *arvif);
|
||||
+int ath11k_nss_ext_vdev_down(struct ath11k_vif *arvif);
|
||||
+void ath11k_nss_ext_vdev_delete(struct ath11k_vif *arvif);
|
||||
int ath11k_nss_set_peer_sec_type(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
struct ieee80211_key_conf *key_conf);
|
||||
-void ath11k_nss_update_sta_stats(struct station_info *sinfo,
|
||||
- struct ieee80211_sta *sta,
|
||||
- struct ath11k_sta *arsta);
|
||||
+void ath11k_nss_update_sta_stats(struct ath11k_vif *arvif,
|
||||
+ struct station_info *sinfo,
|
||||
+ struct ieee80211_sta *sta);
|
||||
void ath11k_nss_update_sta_rxrate(struct hal_rx_mon_ppdu_info *ppdu_info,
|
||||
struct ath11k_peer *peer,
|
||||
struct hal_rx_user_status *user_stats);
|
||||
@@ -257,9 +278,9 @@ static inline void ath11k_nss_vdev_delet
|
||||
{
|
||||
}
|
||||
|
||||
-static inline void ath11k_nss_update_sta_stats(struct station_info *sinfo,
|
||||
- struct ieee80211_sta *sta,
|
||||
- struct ath11k_sta *arsta)
|
||||
+static inline void ath11k_nss_update_sta_stats(struct ath11k_vif *arvif,
|
||||
+ struct station_info *sinfo,
|
||||
+ struct ieee80211_sta *sta)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -316,6 +337,43 @@ static inline int ath11k_nss_peer_create
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static inline int ath11k_nss_ext_vdev_cfg_wds_peer(struct ath11k_vif *arvif,
|
||||
+ u8 *wds_addr, u32 wds_peer_id)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int ath11k_nss_ext_vdev_wds_4addr_allow(struct ath11k_vif *arvif,
|
||||
+ u32 wds_peer_id)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int ath11k_nss_ext_vdev_create(struct ath11k_vif *arvif)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int ath11k_nss_ext_vdev_configure(struct ath11k_vif *arvif)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline void ath11k_nss_ext_vdev_unregister(struct ath11k_vif *arvif)
|
||||
+{
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static inline int ath11k_nss_ext_vdev_up(struct ath11k_vif *arvif)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int ath11k_nss_ext_vdev_down(struct ath11k_vif *arvif)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static inline void ath11k_nss_peer_stats_enable(struct ath11k *ar)
|
||||
{
|
||||
return;
|
||||
@@ -337,6 +395,11 @@ static inline int ath11k_nss_setup(struc
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static inline void ath11k_nss_ext_vdev_delete(struct ath11k_vif *arvif)
|
||||
+{
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
static inline int ath11k_nss_teardown(struct ath11k_base *ab)
|
||||
{
|
||||
return 0;
|
||||
@ -0,0 +1,573 @@
|
||||
From 730f568af3fac2f31467ea0ff374ea442ddc379f Mon Sep 17 00:00:00 2001
|
||||
From: Sathishkumar Muruganandam <murugana@codeaurora.org>
|
||||
Date: Fri, 20 Nov 2020 11:57:36 +0530
|
||||
Subject: [PATCH 3/3] ath11k: add AP_VLAN vif support for WDS offload in NSS
|
||||
offload
|
||||
|
||||
- AP_VLAN vif support is required for WDS offload to interop with mac80211
|
||||
based 4addr STA and also for multicast-to-unicast conversion of 3addr
|
||||
multicast to 4addr frames for each associated 4addr STA.
|
||||
|
||||
- For each associated 4addr STA, corresponding AP_VLAN vif having same MAC
|
||||
address as AP vif is created from hostapd upon 4addr rx_notify from NSS RX.
|
||||
|
||||
- AP_VLAN vif support is added to add/remove interface mac80211 callbacks only
|
||||
for NSS ext vdev handling and vdev_id, FW vdev operations are not needed.
|
||||
|
||||
- mac80211 advertises AP_VLAN vif for sta_use_4addr drv callback in case of
|
||||
NSS offload. Extending ath11k_mac_op_sta_use_4addr to invoke ext vdev NSS
|
||||
APIs required for AP WDS handling.
|
||||
|
||||
- Maintain AP_VLAN vif(s) list on corresponding AP vif and vice versa required
|
||||
for ext vdev operations (VDEV_DOWN, DELETE, CONFIGURE_IF).
|
||||
|
||||
- NSS require ENABLE_NAWDS and WDS_BACKHAUL to be configured for AP_VLAN
|
||||
support via ext vdev.
|
||||
|
||||
Signed-off-by: Sathishkumar Muruganandam <murugana@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/core.h | 1 +
|
||||
drivers/net/wireless/ath/ath11k/mac.c | 156 +++++++++++++++++++++++++++++++--
|
||||
drivers/net/wireless/ath/ath11k/wmi.h | 2 +
|
||||
3 files changed, 154 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/core.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
||||
@@ -434,6 +434,7 @@ struct ath11k_vif {
|
||||
#ifdef CPTCFG_ATH11K_NSS_SUPPORT
|
||||
struct arvif_nss nss;
|
||||
#endif
|
||||
+ struct list_head ap_vlan_arvifs;
|
||||
/* Must be last - ends in a flexible-array member.
|
||||
*
|
||||
* FIXME: Driver should not copy struct ieee80211_chanctx_conf,
|
||||
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
||||
@@ -4844,6 +4844,11 @@ static void ath11k_sta_rc_update_wk(stru
|
||||
arvif = arsta->arvif;
|
||||
ar = arvif->ar;
|
||||
|
||||
+ if (ar->ab->nss.enabled &&
|
||||
+ arsta->arvif->vif->type == NL80211_IFTYPE_AP_VLAN &&
|
||||
+ arsta->use_4addr_set)
|
||||
+ arvif = arvif->nss.ap_vif;
|
||||
+
|
||||
if (WARN_ON(ath11k_mac_vif_chan(arvif->vif, &def)))
|
||||
return;
|
||||
|
||||
@@ -5013,17 +5018,28 @@ err_rc_bw_changed:
|
||||
static void ath11k_sta_set_4addr_wk(struct work_struct *wk)
|
||||
{
|
||||
struct ath11k *ar;
|
||||
- struct ath11k_vif *arvif;
|
||||
+ struct ath11k_vif *arvif, *ap_vlan_arvif = NULL;
|
||||
+ struct ieee80211_vif *vif;
|
||||
struct ath11k_sta *arsta;
|
||||
struct ieee80211_sta *sta;
|
||||
+ struct ath11k_base *ab;
|
||||
+ struct ath11k_peer *wds_peer;
|
||||
+ u8 wds_addr[ETH_ALEN];
|
||||
+ u32 wds_peer_id;
|
||||
int ret = 0;
|
||||
|
||||
arsta = container_of(wk, struct ath11k_sta, set_4addr_wk);
|
||||
sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv);
|
||||
arvif = arsta->arvif;
|
||||
ar = arvif->ar;
|
||||
+ ab = ar->ab;
|
||||
|
||||
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
||||
+ if (ab->nss.enabled && arvif->vif->type == NL80211_IFTYPE_AP_VLAN) {
|
||||
+ ap_vlan_arvif = arsta->arvif;
|
||||
+ arvif = ap_vlan_arvif->nss.ap_vif;
|
||||
+ }
|
||||
+
|
||||
+ ath11k_dbg(ab, ATH11K_DBG_MAC,
|
||||
"setting USE_4ADDR for peer %pM\n", sta->addr);
|
||||
|
||||
ret = ath11k_wmi_set_peer_param(ar, sta->addr,
|
||||
@@ -5031,8 +5047,93 @@ static void ath11k_sta_set_4addr_wk(stru
|
||||
WMI_PEER_USE_4ADDR, 1);
|
||||
|
||||
if (ret)
|
||||
- ath11k_warn(ar->ab, "failed to set peer %pM 4addr capability: %d\n",
|
||||
+ ath11k_warn(ab, "failed to set 4addr for STA %pM: %d\n",
|
||||
sta->addr, ret);
|
||||
+
|
||||
+ if (!ab->nss.enabled || !ap_vlan_arvif)
|
||||
+ return;
|
||||
+
|
||||
+ vif = ap_vlan_arvif->vif;
|
||||
+
|
||||
+ spin_lock_bh(&ab->base_lock);
|
||||
+ wds_peer = ath11k_peer_find_by_addr(ab, sta->addr);
|
||||
+ if (!wds_peer) {
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+ ath11k_warn(ab, "mac sta use 4addr failed to find peer %pM\n",
|
||||
+ sta->addr);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ wds_peer_id = wds_peer->peer_id;
|
||||
+ ether_addr_copy(wds_addr, wds_peer->addr);
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+
|
||||
+ /* skip NSS ext vdev registration if already done */
|
||||
+ if (ap_vlan_arvif->nss.wds_cfg_done)
|
||||
+ goto skip_nss_ext;
|
||||
+
|
||||
+ ret = ath11k_nss_ext_vdev_configure(ap_vlan_arvif);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ab, "failed to nss cfg ext vdev %pM: %d\n",
|
||||
+ vif->addr, ret);
|
||||
+ goto ext_vdev_delete;
|
||||
+ }
|
||||
+
|
||||
+ ap_vlan_arvif->nss.wds_cfg_done = true;
|
||||
+
|
||||
+skip_nss_ext:
|
||||
+
|
||||
+ ret = ath11k_nss_ext_vdev_cfg_wds_peer(ap_vlan_arvif,
|
||||
+ wds_addr, wds_peer_id);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ab, "failed to nss cfg_wds_peer %pM on %pM: %d\n",
|
||||
+ sta->addr, vif->addr, ret);
|
||||
+ goto ext_vdev_delete;
|
||||
+ }
|
||||
+
|
||||
+ ret = ath11k_nss_ext_vdev_wds_4addr_allow(ap_vlan_arvif,
|
||||
+ wds_peer_id);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ab, "failed to nss 4addr allow %pM: %d\n",
|
||||
+ vif->addr, ret);
|
||||
+ goto ext_vdev_delete;
|
||||
+ }
|
||||
+
|
||||
+ ret = ath11k_nss_ext_vdev_up(ap_vlan_arvif);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ab, "failed to nss ext vdev up %pM: %d\n",
|
||||
+ vif->addr, ret);
|
||||
+ goto ext_vdev_delete;
|
||||
+ }
|
||||
+
|
||||
+ 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
|
||||
+ * AP vif of the AP_VLAN vif
|
||||
+ */
|
||||
+ ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
||||
+ WMI_VDEV_PARAM_AP_ENABLE_NAWDS,
|
||||
+ MIN_IDLE_INACTIVE_TIME_SECS);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ab, "failed to set vdev %i nawds parameters: %d\n",
|
||||
+ arvif->vdev_id, ret);
|
||||
+ goto ext_vdev_down;
|
||||
+ }
|
||||
+
|
||||
+ return;
|
||||
+
|
||||
+ext_vdev_down:
|
||||
+ ath11k_nss_ext_vdev_down(ap_vlan_arvif);
|
||||
+ext_vdev_delete:
|
||||
+ ath11k_nss_ext_vdev_delete(ap_vlan_arvif);
|
||||
+
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+ list_del(&ap_vlan_arvif->list);
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
+ ap_vlan_arvif->nss.added = false;
|
||||
}
|
||||
|
||||
static int ath11k_mac_inc_num_stations(struct ath11k_vif *arvif,
|
||||
@@ -5134,9 +5235,32 @@ static void ath11k_mac_op_sta_set_4addr(
|
||||
struct ieee80211_sta *sta, bool enabled)
|
||||
{
|
||||
struct ath11k *ar = hw->priv;
|
||||
+ struct ath11k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
+ struct ath11k_vif *ap_arvif = NULL;
|
||||
|
||||
if (enabled && !arsta->use_4addr_set) {
|
||||
+ if (ar->ab->nss.enabled && vif->type == NL80211_IFTYPE_AP_VLAN) {
|
||||
+ /* 4addr STA is initially associated to AP vif, change
|
||||
+ * it to AP_VLAN vif and add AP_VLAN vif to AP vifs list
|
||||
+ */
|
||||
+ ap_arvif = arsta->arvif;
|
||||
+ arvif->nss.ap_vif = ap_arvif;
|
||||
+
|
||||
+ /* Check if the vlan arvif object was already present in the
|
||||
+ * list. We can receive this path multiple times for the same
|
||||
+ * vlan vif for different sta objects
|
||||
+ */
|
||||
+ if (!arvif->nss.added) {
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+ list_add(&arvif->list, &ap_arvif->ap_vlan_arvifs);
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
+ arvif->nss.added = true;
|
||||
+ }
|
||||
+
|
||||
+ arsta->arvif = arvif;
|
||||
+ }
|
||||
+
|
||||
ieee80211_queue_work(ar->hw, &arsta->set_4addr_wk);
|
||||
arsta->use_4addr_set = true;
|
||||
}
|
||||
@@ -6527,6 +6651,9 @@ static int ath11k_mac_op_update_vif_offl
|
||||
u32 param_id, param_value;
|
||||
int ret;
|
||||
|
||||
+ if (ab->nss.enabled && vif->type == NL80211_IFTYPE_AP_VLAN)
|
||||
+ return 0;
|
||||
+
|
||||
param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE;
|
||||
if (ath11k_frame_mode != ATH11K_HW_TXRX_ETHERNET ||
|
||||
(vif->type != NL80211_IFTYPE_STATION &&
|
||||
@@ -6757,7 +6884,8 @@ static int ath11k_mac_op_add_interface(s
|
||||
goto err;
|
||||
}
|
||||
|
||||
- if (ar->num_created_vdevs > (TARGET_NUM_VDEVS(ab) - 1)) {
|
||||
+ if (vif->type != NL80211_IFTYPE_AP_VLAN &&
|
||||
+ ar->num_created_vdevs > (TARGET_NUM_VDEVS(ab) - 1)) {
|
||||
ath11k_warn(ab, "failed to create vdev %u, reached max vdev limit %d\n",
|
||||
ar->num_created_vdevs, TARGET_NUM_VDEVS(ab));
|
||||
ret = -EBUSY;
|
||||
@@ -6770,6 +6898,28 @@ static int ath11k_mac_op_add_interface(s
|
||||
arvif->vif = vif;
|
||||
|
||||
INIT_LIST_HEAD(&arvif->list);
|
||||
+
|
||||
+ if ((vif->type == NL80211_IFTYPE_AP_VLAN ||
|
||||
+ vif->type == NL80211_IFTYPE_STATION) && ab->nss.enabled) {
|
||||
+ if (ath11k_frame_mode == ATH11K_HW_TXRX_ETHERNET &&
|
||||
+ ieee80211_set_hw_80211_encap(vif, true)) {
|
||||
+ vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
|
||||
+ arvif->nss.encap = ATH11K_HW_TXRX_ETHERNET;
|
||||
+ arvif->nss.decap = ATH11K_HW_TXRX_ETHERNET;
|
||||
+ }
|
||||
+
|
||||
+ if (vif->type == NL80211_IFTYPE_AP_VLAN) {
|
||||
+ ret = ath11k_nss_ext_vdev_create(arvif);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ab, "failed to create ext vdev %pM: %d\n",
|
||||
+ vif->addr, ret);
|
||||
+ goto err;
|
||||
+ }
|
||||
+ mutex_unlock(&ar->conf_mutex);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
INIT_WORK(&arvif->bcn_tx_work, ath11k_mac_bcn_tx_work);
|
||||
INIT_DELAYED_WORK(&arvif->connection_loss_work,
|
||||
ath11k_mac_vif_sta_connection_loss_work);
|
||||
@@ -6802,6 +6952,7 @@ static int ath11k_mac_op_add_interface(s
|
||||
fallthrough;
|
||||
case NL80211_IFTYPE_AP:
|
||||
arvif->vdev_type = WMI_VDEV_TYPE_AP;
|
||||
+ INIT_LIST_HEAD(&arvif->ap_vlan_arvifs);
|
||||
if (vif->p2p)
|
||||
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_GO;
|
||||
break;
|
||||
@@ -7037,14 +7188,31 @@ static void ath11k_mac_op_remove_interfa
|
||||
struct ath11k *ar = hw->priv;
|
||||
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
+ struct ath11k_vif *ap_vlan_arvif, *tmp;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
+ mutex_lock(&ar->conf_mutex);
|
||||
+
|
||||
+ if (vif->type == NL80211_IFTYPE_AP_VLAN) {
|
||||
+ ath11k_nss_ext_vdev_delete(arvif);
|
||||
+
|
||||
+ /* In case the vlan vif never got added into the ap vlan arvifs
|
||||
+ * list, avoid removal here
|
||||
+ */
|
||||
+ if (!arvif->nss.added)
|
||||
+ goto unlock;
|
||||
+
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+ list_del(&arvif->list);
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
+
|
||||
+ goto unlock;
|
||||
+ }
|
||||
+
|
||||
cancel_delayed_work_sync(&arvif->connection_loss_work);
|
||||
cancel_work_sync(&arvif->bcn_tx_work);
|
||||
|
||||
- mutex_lock(&ar->conf_mutex);
|
||||
-
|
||||
ath11k_dbg(ab, ATH11K_DBG_MAC, "remove interface (vdev %d)\n",
|
||||
arvif->vdev_id);
|
||||
|
||||
@@ -7061,6 +7229,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);
|
||||
+
|
||||
+ list_for_each_entry_safe(ap_vlan_arvif, tmp, &arvif->ap_vlan_arvifs,
|
||||
+ list) {
|
||||
+ ath11k_nss_ext_vdev_delete(ap_vlan_arvif);
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+ list_del(&ap_vlan_arvif->list);
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
+ }
|
||||
}
|
||||
|
||||
ret = ath11k_mac_vdev_delete(ar, arvif);
|
||||
@@ -7102,8 +7278,7 @@ err_vdev_del:
|
||||
/* Recalc txpower for remaining vdev */
|
||||
ath11k_mac_txpower_recalc(ar);
|
||||
|
||||
- /* TODO: recal traffic pause state based on the available vdevs */
|
||||
-
|
||||
+unlock:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
@@ -7163,16 +7338,17 @@ static int ath11k_mac_op_ampdu_action(st
|
||||
struct ieee80211_ampdu_params *params)
|
||||
{
|
||||
struct ath11k *ar = hw->priv;
|
||||
+ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
|
||||
int ret = -EINVAL;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
switch (params->action) {
|
||||
case IEEE80211_AMPDU_RX_START:
|
||||
- ret = ath11k_dp_rx_ampdu_start(ar, params);
|
||||
+ ret = ath11k_dp_rx_ampdu_start(arvif, params);
|
||||
break;
|
||||
case IEEE80211_AMPDU_RX_STOP:
|
||||
- ret = ath11k_dp_rx_ampdu_stop(ar, params);
|
||||
+ ret = ath11k_dp_rx_ampdu_stop(arvif, params);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
@@ -9100,6 +9276,7 @@ static void ath11k_mac_op_sta_statistics
|
||||
{
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
|
||||
struct ath11k *ar = arsta->arvif->ar;
|
||||
+ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
|
||||
s8 signal;
|
||||
bool db2dbm = test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
|
||||
ar->ab->wmi_ab.svc_map);
|
||||
@@ -9159,7 +9336,8 @@ static void ath11k_mac_op_sta_statistics
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
--- a/drivers/net/wireless/ath/ath11k/wmi.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
|
||||
@@ -5111,6 +5111,8 @@ enum wmi_vdev_subtype {
|
||||
WMI_VDEV_SUBTYPE_MESH_11S,
|
||||
};
|
||||
|
||||
+#define MIN_IDLE_INACTIVE_TIME_SECS 256
|
||||
+
|
||||
enum wmi_sta_powersave_param {
|
||||
WMI_STA_PS_PARAM_RX_WAKE_POLICY = 0,
|
||||
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
|
||||
@@ -1122,12 +1122,13 @@ err_mem_free:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-int ath11k_dp_rx_ampdu_start(struct ath11k *ar,
|
||||
+int ath11k_dp_rx_ampdu_start(struct ath11k_vif *arvif,
|
||||
struct ieee80211_ampdu_params *params)
|
||||
{
|
||||
+ struct ath11k *ar = arvif->ar;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ath11k_sta *arsta = ath11k_sta_to_arsta(params->sta);
|
||||
- int vdev_id = arsta->arvif->vdev_id;
|
||||
+ int vdev_id = arvif->vdev_id;
|
||||
int ret;
|
||||
|
||||
ret = ath11k_peer_rx_tid_setup(ar, params->sta->addr, vdev_id,
|
||||
@@ -1139,13 +1140,13 @@ int ath11k_dp_rx_ampdu_start(struct ath1
|
||||
return ret;
|
||||
}
|
||||
|
||||
-int ath11k_dp_rx_ampdu_stop(struct ath11k *ar,
|
||||
+int ath11k_dp_rx_ampdu_stop(struct ath11k_vif *arvif,
|
||||
struct ieee80211_ampdu_params *params)
|
||||
{
|
||||
+ struct ath11k *ar = arvif->ar;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ath11k_peer *peer;
|
||||
- struct ath11k_sta *arsta = ath11k_sta_to_arsta(params->sta);
|
||||
- int vdev_id = arsta->arvif->vdev_id;
|
||||
+ int vdev_id = arvif->vdev_id;
|
||||
dma_addr_t paddr;
|
||||
bool active;
|
||||
int ret;
|
||||
--- a/drivers/net/wireless/ath/ath11k/dp_rx.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.h
|
||||
@@ -89,9 +89,9 @@ static inline u32 ath11k_he_gi_to_nl8021
|
||||
return ret;
|
||||
}
|
||||
|
||||
-int ath11k_dp_rx_ampdu_start(struct ath11k *ar,
|
||||
+int ath11k_dp_rx_ampdu_start(struct ath11k_vif *arvif,
|
||||
struct ieee80211_ampdu_params *params);
|
||||
-int ath11k_dp_rx_ampdu_stop(struct ath11k *ar,
|
||||
+int ath11k_dp_rx_ampdu_stop(struct ath11k_vif *arvif,
|
||||
struct ieee80211_ampdu_params *params);
|
||||
int ath11k_dp_peer_rx_pn_replay_config(struct ath11k_vif *arvif,
|
||||
const u8 *peer_addr,
|
||||
--- a/drivers/net/wireless/ath/ath11k/peer.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/peer.c
|
||||
@@ -140,6 +140,24 @@ struct ath11k_ast_entry *ath11k_peer_ast
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+struct ath11k_ast_entry *ath11k_peer_ast_find_by_pdev_idx(struct ath11k *ar,
|
||||
+ u8* addr)
|
||||
+{
|
||||
+ struct ath11k_base *ab = ar->ab;
|
||||
+ struct ath11k_ast_entry *ast_entry;
|
||||
+ struct ath11k_peer *peer;
|
||||
+
|
||||
+ lockdep_assert_held(&ab->base_lock);
|
||||
+
|
||||
+ list_for_each_entry(peer, &ab->peers, list)
|
||||
+ list_for_each_entry(ast_entry, &peer->ast_entry_list, ase_list)
|
||||
+ if (ether_addr_equal(ast_entry->addr, addr) &&
|
||||
+ ast_entry->pdev_idx == ar->pdev_idx)
|
||||
+ return ast_entry;
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
void ath11k_peer_ast_wds_wmi_wk(struct work_struct *wk)
|
||||
{
|
||||
struct ath11k_ast_entry *ast_entry = container_of(wk,
|
||||
@@ -200,8 +218,8 @@ int ath11k_peer_add_ast(struct ath11k *a
|
||||
}
|
||||
|
||||
if (type != ATH11K_AST_TYPE_STATIC) {
|
||||
- ast_entry = ath11k_peer_ast_find_by_addr(ab, mac_addr);
|
||||
- if (ast_entry) {
|
||||
+ ast_entry = ath11k_peer_ast_find_by_pdev_idx(ar, mac_addr);
|
||||
+ if (ast_entry && ast_entry->type != ATH11K_AST_TYPE_STATIC) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_MAC, "ast_entry %pM already present on peer %pM\n",
|
||||
mac_addr, ast_entry->peer->addr);
|
||||
return 0;
|
||||
@@ -298,7 +316,6 @@ int ath11k_peer_update_ast(struct ath11k
|
||||
ath11k_dbg(ab, ATH11K_DBG_MAC, "ath11k_peer_update_ast old peer %pM new peer %pM ast_entry %pM\n",
|
||||
old_peer->addr, peer->addr, ast_entry->addr);
|
||||
|
||||
- flush_work(&ast_entry->wds_wmi_wk);
|
||||
ast_entry->action = ATH11K_WDS_WMI_UPDATE;
|
||||
ieee80211_queue_work(ar->hw, &ast_entry->wds_wmi_wk);
|
||||
|
||||
@@ -343,8 +360,8 @@ void ath11k_peer_del_ast(struct ath11k *
|
||||
|
||||
peer = ast_entry->peer;
|
||||
|
||||
- ath11k_dbg(ab, ATH11K_DBG_MAC, "ath11k_peer_del_ast peer %pM ast_entry %pM\n",
|
||||
- peer->addr, ast_entry->addr);
|
||||
+ 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);
|
||||
|
||||
if (ast_entry->is_mapped)
|
||||
list_del(&ast_entry->ase_list);
|
||||
--- a/drivers/net/wireless/ath/ath11k/peer.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/peer.h
|
||||
@@ -34,6 +34,7 @@ enum ath11k_ast_entry_type {
|
||||
enum ath11k_wds_wmi_action {
|
||||
ATH11K_WDS_WMI_ADD = 1,
|
||||
ATH11K_WDS_WMI_UPDATE,
|
||||
+ ATH11K_WDS_WMI_REMOVE,
|
||||
|
||||
ATH11K_WDS_WMI_MAX
|
||||
};
|
||||
@@ -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);
|
||||
+struct ath11k_ast_entry *ath11k_peer_ast_find_by_pdev_idx(struct ath11k *ar,
|
||||
+ u8* addr);
|
||||
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,
|
||||
@@ -146,6 +149,12 @@ static inline struct ath11k_ast_entry *a
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
+
|
||||
+static inline struct ath11k_ast_entry *ath11k_peer_ast_find_by_pdev_idx(struct ath11k *ar,
|
||||
+ u8* addr)
|
||||
+{
|
||||
+ return NULL;
|
||||
+}
|
||||
|
||||
static inline int ath11k_peer_add_ast(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
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
|
||||
@@ -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(rx, peer->nss.ext_vif, rx_bytes, rx_packets);
|
||||
+ else
|
||||
+ ATH11K_NSS_TXRX_NETDEV_STATS(rx, peer->vif, rx_bytes, rx_packets);
|
||||
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
rcu_read_unlock();
|
||||
@@ -1000,6 +1006,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;
|
||||
+ case ATH11K_NSS_WIFI_VDEV_CFG_WDS_BACKHAUL_CMD:
|
||||
+ cmd = NSS_WIFI_VDEV_CFG_WDS_BACKHAUL_CMD;
|
||||
+ break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
--- a/drivers/net/wireless/ath/ath11k/nss.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/nss.h
|
||||
@@ -108,6 +108,7 @@ enum ath11k_nss_vdev_cmd {
|
||||
ATH11K_NSS_WIFI_VDEV_SECURITY_TYPE_CMD,
|
||||
ATH11K_NSS_WIFI_VDEV_ENCAP_TYPE_CMD,
|
||||
ATH11K_NSS_WIFI_VDEV_DECAP_TYPE_CMD,
|
||||
+ ATH11K_NSS_WIFI_VDEV_CFG_WDS_BACKHAUL_CMD,
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
@ -0,0 +1,213 @@
|
||||
From 6f51430f2614ca2fb2a1e45cc81464c6d7a29f03 Mon Sep 17 00:00:00 2001
|
||||
From: Sathishkumar Muruganandam <murugana@codeaurora.org>
|
||||
Date: Fri, 8 Jan 2021 00:34:09 +0530
|
||||
Subject: [PATCH 2/3] ath11k: extend ext vdev in NSS for dynamic VLAN handling
|
||||
|
||||
- add ext vdev NSS API callbacks required for dynamic AP_VLAN vif
|
||||
- existing ext vdev NSS API callbacks are used for both WDS and
|
||||
dynamic VLAN di_types.
|
||||
|
||||
Signed-off-by: Sathishkumar Muruganandam <murugana@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/nss.c | 101 +++++++++++++++++++++++++++++++---
|
||||
drivers/net/wireless/ath/ath11k/nss.h | 17 ++++++
|
||||
2 files changed, 109 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/nss.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/nss.c
|
||||
@@ -1530,14 +1530,11 @@ static int ath11k_nss_ext_vdev_register(
|
||||
struct ath11k *ar = arvif->ar;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
nss_tx_status_t status;
|
||||
- enum nss_dynamic_interface_type di_type;
|
||||
u32 features = 0;
|
||||
|
||||
if (arvif->vif->type != NL80211_IFTYPE_AP_VLAN || arvif->nss.ctx)
|
||||
return -EINVAL;
|
||||
|
||||
- di_type = NSS_DYNAMIC_INTERFACE_TYPE_WIFI_EXT_VDEV_WDS;
|
||||
-
|
||||
arvif->nss.ctx = nss_wifi_ext_vdev_register_if(arvif->nss.if_num,
|
||||
ath11k_nss_ext_vdev_data_receive,
|
||||
ath11k_nss_ext_vdev_special_data_receive,
|
||||
@@ -1565,7 +1562,8 @@ static void ath11k_nss_ext_vdev_free(str
|
||||
|
||||
status = nss_dynamic_interface_dealloc_node(
|
||||
arvif->nss.if_num,
|
||||
- NSS_DYNAMIC_INTERFACE_TYPE_WIFI_EXT_VDEV_WDS);
|
||||
+ arvif->nss.di_type);
|
||||
+
|
||||
if (status != NSS_TX_SUCCESS)
|
||||
ath11k_warn(ab, "failed to free nss ext vdev err:%d\n",
|
||||
status);
|
||||
@@ -1574,14 +1572,19 @@ static void ath11k_nss_ext_vdev_free(str
|
||||
"nss ext vdev interface deallocated\n");
|
||||
}
|
||||
|
||||
-static int ath11k_nss_ext_vdev_alloc(struct ath11k_vif *arvif)
|
||||
+static int ath11k_nss_ext_vdev_alloc(struct ath11k_vif *arvif,
|
||||
+ struct wireless_dev *wdev)
|
||||
{
|
||||
struct ath11k_base *ab = arvif->ar->ab;
|
||||
enum nss_dynamic_interface_type di_type;
|
||||
int if_num;
|
||||
|
||||
- di_type = NSS_DYNAMIC_INTERFACE_TYPE_WIFI_EXT_VDEV_WDS;
|
||||
+ if (wdev->use_4addr)
|
||||
+ di_type = NSS_DYNAMIC_INTERFACE_TYPE_WIFI_EXT_VDEV_WDS;
|
||||
+ else
|
||||
+ di_type = NSS_DYNAMIC_INTERFACE_TYPE_WIFI_EXT_VDEV_VLAN;
|
||||
|
||||
+ arvif->nss.di_type = di_type;
|
||||
if_num = nss_dynamic_interface_alloc_node(di_type);
|
||||
if (if_num < 0) {
|
||||
ath11k_warn(ab, "failed to allocate nss ext vdev\n");
|
||||
@@ -1590,8 +1593,8 @@ static int ath11k_nss_ext_vdev_alloc(str
|
||||
|
||||
arvif->nss.if_num = if_num;
|
||||
ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
||||
- "nss ext vdev interface %pM allocated if_num %d\n",
|
||||
- arvif->vif->addr, if_num);
|
||||
+ "nss ext vdev interface %pM di_type %d allocated if_num %d\n",
|
||||
+ arvif->vif->addr, di_type, if_num);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1620,7 +1623,7 @@ int ath11k_nss_ext_vdev_create(struct at
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- ret = ath11k_nss_ext_vdev_alloc(arvif);
|
||||
+ ret = ath11k_nss_ext_vdev_alloc(arvif, wdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1733,6 +1736,86 @@ free:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+int ath11k_nss_ext_vdev_cfg_dyn_vlan(struct ath11k_vif *arvif, u16 vlan_id)
|
||||
+{
|
||||
+ struct ath11k *ar = arvif->ar;
|
||||
+ struct nss_wifi_ext_vdev_msg *ext_vdev_msg = NULL;
|
||||
+ struct nss_wifi_ext_vdev_vlan_msg *cfg_dyn_vlan_msg = NULL;
|
||||
+ nss_tx_status_t status;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!ar->ab->nss.enabled)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (arvif->vif->type != NL80211_IFTYPE_AP_VLAN)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ ext_vdev_msg = kzalloc(sizeof(struct nss_wifi_ext_vdev_msg), GFP_ATOMIC);
|
||||
+ if (!ext_vdev_msg)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ cfg_dyn_vlan_msg = &ext_vdev_msg->msg.vmsg;
|
||||
+ cfg_dyn_vlan_msg->vlan_id = vlan_id;
|
||||
+
|
||||
+ nss_wifi_ext_vdev_msg_init(ext_vdev_msg, arvif->nss.if_num,
|
||||
+ NSS_WIFI_EXT_VDEV_MSG_CONFIGURE_VLAN,
|
||||
+ sizeof(struct nss_wifi_ext_vdev_vlan_msg),
|
||||
+ NULL, arvif);
|
||||
+
|
||||
+ status = nss_wifi_ext_vdev_tx_msg_sync(arvif->nss.ctx, ext_vdev_msg);
|
||||
+ if (status != NSS_TX_SUCCESS) {
|
||||
+ ath11k_warn(ar->ab, "failed to configure dyn vlan nss_err:%d\n",
|
||||
+ status);
|
||||
+ ret = -EINVAL;
|
||||
+ goto free;
|
||||
+ }
|
||||
+
|
||||
+ ret = 0;
|
||||
+free:
|
||||
+ kfree(ext_vdev_msg);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int ath11k_nss_dyn_vlan_set_group_key(struct ath11k_vif *arvif, u16 vlan_id,
|
||||
+ u16 group_key)
|
||||
+{
|
||||
+ struct nss_wifi_vdev_msg *vdev_msg = NULL;
|
||||
+ struct nss_wifi_vdev_set_vlan_group_key *vlan_group_key;
|
||||
+ struct ath11k *ar = arvif->ar;
|
||||
+ nss_tx_status_t status;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ if (!ar->ab->nss.enabled)
|
||||
+ return 0;
|
||||
+
|
||||
+ vdev_msg = kzalloc(sizeof(struct nss_wifi_vdev_msg), GFP_ATOMIC);
|
||||
+ if (!vdev_msg)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ vlan_group_key = &vdev_msg->msg.vlan_group_key;
|
||||
+ vlan_group_key->vlan_id = vlan_id;
|
||||
+ vlan_group_key->group_key = group_key;
|
||||
+
|
||||
+ nss_wifi_vdev_msg_init(vdev_msg, arvif->nss.if_num,
|
||||
+ NSS_WIFI_VDEV_SET_GROUP_KEY,
|
||||
+ sizeof(struct nss_wifi_vdev_set_vlan_group_key),
|
||||
+ NULL, NULL);
|
||||
+
|
||||
+ status = nss_wifi_vdev_tx_msg(ar->nss.ctx, vdev_msg);
|
||||
+ if (status != NSS_TX_SUCCESS) {
|
||||
+ ath11k_warn(ar->ab, "nss vdev set vlan group key error %d\n", status);
|
||||
+ ret = -EINVAL;
|
||||
+ goto free;
|
||||
+ }
|
||||
+
|
||||
+ ath11k_dbg(ar->ab, ATH11K_DBG_NSS_WDS, "nss vdev set vlan group key success\n");
|
||||
+free:
|
||||
+ kfree(vdev_msg);
|
||||
+ return ret;
|
||||
+
|
||||
+}
|
||||
+
|
||||
/*----------------------------Peer Setup/Config -----------------------------*/
|
||||
|
||||
int ath11k_nss_set_peer_sec_type(struct ath11k *ar,
|
||||
--- a/drivers/net/wireless/ath/ath11k/nss.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/nss.h
|
||||
@@ -176,6 +176,10 @@ struct arvif_nss {
|
||||
bool added;
|
||||
/* Flag to notify if ext vdev is up/down */
|
||||
bool ext_vdev_up;
|
||||
+#ifdef CPTCFG_ATH11K_NSS_SUPPORT
|
||||
+ /* Keep the copy of di_type for nss */
|
||||
+ enum nss_dynamic_interface_type di_type;
|
||||
+#endif
|
||||
/* WDS cfg should be done only once for ext vdev */
|
||||
bool wds_cfg_done;
|
||||
bool created;
|
||||
@@ -243,6 +247,9 @@ void ath11k_nss_ext_vdev_unregister(stru
|
||||
int ath11k_nss_ext_vdev_up(struct ath11k_vif *arvif);
|
||||
int ath11k_nss_ext_vdev_down(struct ath11k_vif *arvif);
|
||||
void ath11k_nss_ext_vdev_delete(struct ath11k_vif *arvif);
|
||||
+int ath11k_nss_ext_vdev_cfg_dyn_vlan(struct ath11k_vif *arvif, u16 vlan_id);
|
||||
+int ath11k_nss_dyn_vlan_set_group_key(struct ath11k_vif *arvif, u16 vlan_id,
|
||||
+ u16 group_key);
|
||||
int ath11k_nss_set_peer_sec_type(struct ath11k *ar, struct ath11k_peer *peer,
|
||||
struct ieee80211_key_conf *key_conf);
|
||||
void ath11k_nss_update_sta_stats(struct ath11k_vif *arvif,
|
||||
@@ -375,6 +382,18 @@ static inline int ath11k_nss_ext_vdev_do
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+static inline int ath11k_nss_ext_vdev_cfg_dyn_vlan(struct ath11k_vif *arvif,
|
||||
+ u16 vlan_id)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int ath11k_nss_dyn_vlan_set_group_key(struct ath11k_vif *arvif,
|
||||
+ u16 vlan_id, u16 group_key)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
|
||||
static inline void ath11k_nss_peer_stats_enable(struct ath11k *ar)
|
||||
{
|
||||
@ -0,0 +1,557 @@
|
||||
From da432fe6dda831c867416d338def3e277c989287 Mon Sep 17 00:00:00 2001
|
||||
From: Sathishkumar Muruganandam <murugana@codeaurora.org>
|
||||
Date: Fri, 8 Jan 2021 00:39:47 +0530
|
||||
Subject: [PATCH 3/3] ath11k: add dynamic VLAN support in NSS offload
|
||||
|
||||
Driver should advertise NL80211_EXT_FEATURE_VLAN_OFFLOAD to enable
|
||||
vlan offload in hostapd.
|
||||
|
||||
Group Key for multiple vlan interfaces are configured with the help
|
||||
of group key index as NSS uses this index to get the corresponding
|
||||
group key during transmission.
|
||||
|
||||
Each dynamic AP-VLAN interface choose unique group key index which
|
||||
will be sent to NSS along with VLAN ID for dynamic VLAN ext vdev
|
||||
configuration.
|
||||
|
||||
ath11k_mac_op_set_key() does the NSS ext vdev config upon receiving
|
||||
VLAN ID on group key.
|
||||
|
||||
ath11k_mac_op_sta_state() does the STA assignment from AP vif to
|
||||
AP_VLAN vif in NSS after mac80211.
|
||||
|
||||
Currently, the firmware supports upto 128 group keys for an AP
|
||||
interface. The multiple group key support can be enabled during
|
||||
resource config.
|
||||
|
||||
Co-Developed-by: Seevalamuthu Mariappan <seevalam@codeaurora.org>
|
||||
Signed-off-by: Seevalamuthu Mariappan <seevalam@codeaurora.org>
|
||||
Signed-off-by: Sathishkumar Muruganandam <murugana@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/core.h | 8 ++
|
||||
drivers/net/wireless/ath/ath11k/mac.c | 237 ++++++++++++++++++++++++++++++---
|
||||
drivers/net/wireless/ath/ath11k/wmi.c | 5 +
|
||||
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
|
||||
@@ -105,6 +105,11 @@ enum ath11k_crypt_mode {
|
||||
ATH11K_CRYPT_MODE_SW,
|
||||
};
|
||||
|
||||
+#define ATH11K_GROUP_KEYS_NUM_MAX 128
|
||||
+#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 :
|
||||
@@ -374,6 +379,20 @@ struct ath11k_mgmt_frame_stats {
|
||||
u32 tx_compl_fail[ATH11K_STATS_MGMT_FRM_TYPE_MAX];
|
||||
};
|
||||
|
||||
+/**
|
||||
+ *struct ath11k_dyn_vlan_cfg - dynamic vlan config state info container.
|
||||
+ * will be used during ieee80211_reconfig
|
||||
+ * nss offload case
|
||||
+ *@arvif: driver's data for the corresponding AP_VLAN ieee80211_vif
|
||||
+ *@sta: ieee80211_sta which is getting associated to AP_VLAN
|
||||
+ *@cfg_list: list to hold all associated sta's state
|
||||
+ */
|
||||
+struct ath11k_dyn_vlan_cfg {
|
||||
+ struct ath11k_vif *arvif;
|
||||
+ struct ieee80211_sta *sta;
|
||||
+ struct list_head cfg_list;
|
||||
+};
|
||||
+
|
||||
struct ath11k_vif {
|
||||
u32 vdev_id;
|
||||
enum wmi_vdev_type vdev_type;
|
||||
@@ -435,6 +454,11 @@ struct ath11k_vif {
|
||||
struct arvif_nss nss;
|
||||
#endif
|
||||
struct list_head ap_vlan_arvifs;
|
||||
+ /* list required by Dynamic VLAN during fw_recovery */
|
||||
+ struct list_head dyn_vlan_cfg;
|
||||
+ /* VLAN keyidx map required for Dynamic VLAN */
|
||||
+ u16 *vlan_keyid_map;
|
||||
+ DECLARE_BITMAP(free_groupidx_map, ATH11K_GROUP_KEYS_NUM_MAX);
|
||||
/* Must be last - ends in a flexible-array member.
|
||||
*
|
||||
* FIXME: Driver should not copy struct ieee80211_chanctx_conf,
|
||||
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
||||
@@ -343,6 +343,10 @@ enum nl80211_he_gi ath11k_mac_he_gi_to_n
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int ath11k_mac_cfg_dyn_vlan(struct ath11k_base *ab,
|
||||
+ struct ath11k_vif *ap_vlan_arvif,
|
||||
+ struct ieee80211_sta *sta);
|
||||
+
|
||||
u8 ath11k_mac_bw_to_mac80211_bw(u8 bw)
|
||||
{
|
||||
u8 ret = 0;
|
||||
@@ -715,6 +719,33 @@ u8 ath11k_mac_get_target_pdev_id(struct
|
||||
return ar->ab->target_pdev_ids[0].pdev_id;
|
||||
}
|
||||
|
||||
+struct ath11k_vif *ath11k_mac_get_ap_arvif_by_addr(struct ath11k_base *ab,
|
||||
+ const u8 *addr)
|
||||
+{
|
||||
+ int i;
|
||||
+ struct ath11k_pdev *pdev;
|
||||
+ struct ath11k_vif *arvif;
|
||||
+ struct ath11k *ar;
|
||||
+
|
||||
+ for (i = 0; i < ab->num_radios; i++) {
|
||||
+ pdev = rcu_dereference(ab->pdevs_active[i]);
|
||||
+ if (pdev && pdev->ar) {
|
||||
+ ar = pdev->ar;
|
||||
+
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+ list_for_each_entry(arvif, &ar->arvifs, list) {
|
||||
+ if (arvif->vif->type == NL80211_IFTYPE_AP &&
|
||||
+ ether_addr_equal(arvif->vif->addr, addr)) {
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
+ return arvif;
|
||||
+ }
|
||||
+ }
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
+ }
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static void ath11k_pdev_caps_update(struct ath11k *ar)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
@@ -4265,6 +4296,9 @@ static int ath11k_install_key(struct ath
|
||||
if (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
|
||||
return 0;
|
||||
|
||||
+ if (key->vlan_id)
|
||||
+ arg.group_key_idx = key->hw_key_idx;
|
||||
+
|
||||
if (cmd == DISABLE_KEY) {
|
||||
arg.key_cipher = WMI_CIPHER_NONE;
|
||||
arg.key_data = NULL;
|
||||
@@ -4353,15 +4387,40 @@ static int ath11k_clear_peer_keys(struct
|
||||
return first_errno;
|
||||
}
|
||||
|
||||
+static int ath11k_get_vlan_groupkey_index(struct ath11k_vif *arvif,
|
||||
+ struct ieee80211_key_conf *key)
|
||||
+{
|
||||
+ struct ath11k *ar = arvif->ar;
|
||||
+ int map_idx = 0;
|
||||
+ int free_bit;
|
||||
+
|
||||
+ for (map_idx = 0; map_idx < ATH11K_FREE_GROUP_IDX_MAP_MAX; map_idx++)
|
||||
+ if (arvif->free_groupidx_map[map_idx] != 0)
|
||||
+ break;
|
||||
+
|
||||
+ if (map_idx == ATH11K_FREE_GROUP_IDX_MAP_MAX)
|
||||
+ return -ENOSPC;
|
||||
+
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+ /* select the first free key index */
|
||||
+ free_bit = __ffs64(arvif->free_groupidx_map[map_idx]);
|
||||
+ key->hw_key_idx = (map_idx * ATH11K_FREE_GROUP_IDX_MAP_BITS) + free_bit;
|
||||
+ /* clear the selected bit from free index map */
|
||||
+ clear_bit(key->hw_key_idx, arvif->free_groupidx_map);
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct ath11k *ar = hw->priv;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
- struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
|
||||
+ struct ath11k_vif *arvif, *ap_vlan_arvif = NULL;
|
||||
struct ath11k_peer *peer;
|
||||
- struct ath11k_sta *arsta;
|
||||
+ struct ath11k_sta *arsta = NULL;
|
||||
const u8 *peer_addr;
|
||||
int ret = 0;
|
||||
u32 flags = 0;
|
||||
@@ -4379,17 +4438,38 @@ static int ath11k_mac_op_set_key(struct
|
||||
if (key->keyidx > WMI_MAX_KEY_INDEX)
|
||||
return -ENOSPC;
|
||||
|
||||
- mutex_lock(&ar->conf_mutex);
|
||||
+ arvif = ath11k_vif_to_arvif(vif);
|
||||
|
||||
- if (sta)
|
||||
+ mutex_lock(&ar->conf_mutex);
|
||||
+ if (sta) {
|
||||
peer_addr = sta->addr;
|
||||
- else if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
|
||||
+ arsta = (struct ath11k_sta *)sta->drv_priv;
|
||||
+ } else if (arvif->vdev_type == WMI_VDEV_TYPE_STA) {
|
||||
peer_addr = vif->bss_conf.bssid;
|
||||
- else
|
||||
+ } else {
|
||||
peer_addr = vif->addr;
|
||||
+ }
|
||||
|
||||
key->hw_key_idx = key->keyidx;
|
||||
|
||||
+ if (ab->nss.enabled && vif->type == NL80211_IFTYPE_AP_VLAN) {
|
||||
+ ap_vlan_arvif = arvif;
|
||||
+ if (arsta) {
|
||||
+ ap_vlan_arvif->nss.ap_vif = arsta->arvif;
|
||||
+ arvif = arsta->arvif;
|
||||
+ } else {
|
||||
+ rcu_read_lock();
|
||||
+ arvif = ath11k_mac_get_ap_arvif_by_addr(ab, peer_addr);
|
||||
+ if (!arvif) {
|
||||
+ rcu_read_unlock();
|
||||
+ ret = -EINVAL;
|
||||
+ goto exit;
|
||||
+ }
|
||||
+ ap_vlan_arvif->nss.ap_vif = arvif;
|
||||
+ rcu_read_unlock();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* 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.
|
||||
*/
|
||||
@@ -4434,6 +4514,74 @@ static int ath11k_mac_op_set_key(struct
|
||||
goto exit;
|
||||
}
|
||||
|
||||
+ /* VLAN ID is updated non-zero only for AP_VLAN vif */
|
||||
+ if (key->vlan_id && !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE) &&
|
||||
+ ap_vlan_arvif) {
|
||||
+ if (arvif->vlan_keyid_map)
|
||||
+ key->hw_key_idx = arvif->vlan_keyid_map[key->vlan_id];
|
||||
+ else
|
||||
+ key->hw_key_idx = 0;
|
||||
+ switch (cmd) {
|
||||
+ case SET_KEY:
|
||||
+ /* If the group key idx is already available,
|
||||
+ * no need to find the free index again.
|
||||
+ * This happens during GTK rekey. It uses
|
||||
+ * the same index after rekey also.
|
||||
+ */
|
||||
+ if (!key->hw_key_idx)
|
||||
+ ret = ath11k_get_vlan_groupkey_index(arvif, key);
|
||||
+ break;
|
||||
+ case DISABLE_KEY:
|
||||
+ /* If the group key idx is already 0,
|
||||
+ * no need of freeing the index.
|
||||
+ */
|
||||
+ if (key->hw_key_idx) {
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+ /* make the group index as available */
|
||||
+ set_bit(key->hw_key_idx, arvif->free_groupidx_map);
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
+ }
|
||||
+ break;
|
||||
+ default:
|
||||
+ ret = -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ab, "failed to set group key index for vlan %u : %d\n",
|
||||
+ key->vlan_id, ret);
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ ret = ath11k_nss_ext_vdev_configure(ap_vlan_arvif);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ab, "failed to nss cfg ext vdev %pM: %d\n",
|
||||
+ ap_vlan_arvif->vif->addr, ret);
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ ret = ath11k_nss_ext_vdev_cfg_dyn_vlan(ap_vlan_arvif,
|
||||
+ key->vlan_id);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ab, "failed to cfg dynamic vlan %d\n", ret);
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ ret = ath11k_nss_dyn_vlan_set_group_key(ap_vlan_arvif->nss.ap_vif,
|
||||
+ key->vlan_id,
|
||||
+ key->hw_key_idx);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ab, "failed to set dynamic vlan group key %d\n",
|
||||
+ ret);
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ ret = ath11k_nss_ext_vdev_up(ap_vlan_arvif);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ab, "failed to set dyn vlan UP %d\n", ret);
|
||||
+ goto exit;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
peer = ath11k_peer_find(ab, arvif->vdev_id, peer_addr);
|
||||
|
||||
@@ -4456,6 +4604,27 @@ static int ath11k_mac_op_set_key(struct
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
+ spin_unlock_bh(&ar->ab->base_lock);
|
||||
+ if (ap_vlan_arvif && ar->state == ATH11K_STATE_RESTARTED) {
|
||||
+ /* Keys are getting installed during ieee80211_reconfig(). Configuring
|
||||
+ * dynamic vlan is pending and the state is saved in the ap_vlan
|
||||
+ * arvif dyn_vlan_cfg list. We will configure it now since nss peer is authorised */
|
||||
+ struct ath11k_dyn_vlan_cfg *dyn_vlan_cfg, *tmp;
|
||||
+
|
||||
+ list_for_each_entry_safe(dyn_vlan_cfg, tmp, &ap_vlan_arvif->dyn_vlan_cfg, cfg_list) {
|
||||
+ struct ieee80211_sta *vlan_sta = dyn_vlan_cfg->sta;
|
||||
+
|
||||
+ ret = ath11k_mac_cfg_dyn_vlan(ar->ab, ap_vlan_arvif, vlan_sta);
|
||||
+ if (ret)
|
||||
+ ath11k_warn(ar->ab, "failed to cfg dyn vlan for peer %pM: %d\n",
|
||||
+ vlan_sta->addr, ret);
|
||||
+ /* Configuration is used. Free up space */
|
||||
+ list_del(&dyn_vlan_cfg->cfg_list);
|
||||
+ kfree(dyn_vlan_cfg);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ spin_lock_bh(&ar->ab->base_lock);
|
||||
if (peer && cmd == SET_KEY) {
|
||||
peer->keys[key->keyidx] = key;
|
||||
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
|
||||
@@ -4465,18 +4634,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);
|
||||
}
|
||||
+ /* storing group key idx which will be used during rekey */
|
||||
+ if (key->vlan_id)
|
||||
+ arvif->vlan_keyid_map[key->vlan_id] = key->hw_key_idx;
|
||||
} else if (peer && cmd == DISABLE_KEY) {
|
||||
peer->keys[key->keyidx] = NULL;
|
||||
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
|
||||
peer->ucast_keyidx = 0;
|
||||
else
|
||||
peer->mcast_keyidx = 0;
|
||||
- } else if (!peer)
|
||||
+ if (key->vlan_id)
|
||||
+ arvif->vlan_keyid_map[key->vlan_id] = 0;
|
||||
+ } else if (!peer) {
|
||||
/* impossible unless FW goes crazy */
|
||||
ath11k_warn(ab, "peer %pM disappeared!\n", peer_addr);
|
||||
+ }
|
||||
|
||||
- if (sta) {
|
||||
- arsta = ath11k_sta_to_arsta(sta);
|
||||
+ if (arsta) {
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
@@ -6902,7 +7076,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 &&
|
||||
- ieee80211_set_hw_80211_encap(vif, true)) {
|
||||
+ (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)) {
|
||||
vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
|
||||
arvif->nss.encap = ATH11K_HW_TXRX_ETHERNET;
|
||||
arvif->nss.decap = ATH11K_HW_TXRX_ETHERNET;
|
||||
@@ -6915,6 +7089,7 @@ static int ath11k_mac_op_add_interface(s
|
||||
vif->addr, ret);
|
||||
goto err;
|
||||
}
|
||||
+ INIT_LIST_HEAD(&arvif->dyn_vlan_cfg);
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return ret;
|
||||
}
|
||||
@@ -6940,6 +7115,20 @@ static int ath11k_mac_op_add_interface(s
|
||||
arvif->vdev_id = bit;
|
||||
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
|
||||
|
||||
+ spin_lock_bh(&ar->data_lock);
|
||||
+ /* Configure vlan specific parameters */
|
||||
+ for (i = 0; i < ATH11K_FREE_GROUP_IDX_MAP_MAX; i++)
|
||||
+ arvif->free_groupidx_map[i] = 0xFFFFFFFFL;
|
||||
+ /* Group idx 0 is not valid for VLAN*/
|
||||
+ arvif->free_groupidx_map[0] &= ~(1L);
|
||||
+ spin_unlock_bh(&ar->data_lock);
|
||||
+
|
||||
+ arvif->vlan_keyid_map = kzalloc(4096, GFP_KERNEL);
|
||||
+ if (!arvif->vlan_keyid_map) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_UNSPECIFIED:
|
||||
case NL80211_IFTYPE_STATION:
|
||||
@@ -6989,7 +7178,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);
|
||||
- goto err;
|
||||
+ goto err_keyid;
|
||||
}
|
||||
|
||||
ar->num_created_vdevs++;
|
||||
@@ -7154,7 +7343,7 @@ err_peer_del:
|
||||
if (fbret) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7165,6 +7354,8 @@ err_vdev_del:
|
||||
list_del(&arvif->list);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
+err_keyid:
|
||||
+ kfree(arvif->vlan_keyid_map);
|
||||
err:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
@@ -7263,6 +7454,7 @@ err_vdev_del:
|
||||
list_del(&arvif->list);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
+ kfree(arvif->vlan_keyid_map);
|
||||
ath11k_peer_cleanup(ar, arvif->vdev_id);
|
||||
|
||||
idr_for_each(&ar->txmgmt_idr,
|
||||
@@ -9887,6 +10079,33 @@ static int ath11k_mac_station_remove(str
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int ath11k_mac_cfg_dyn_vlan(struct ath11k_base *ab,
|
||||
+ struct ath11k_vif *ap_vlan_arvif,
|
||||
+ struct ieee80211_sta *sta)
|
||||
+{
|
||||
+ struct ath11k_peer *peer;
|
||||
+ int peer_id, ret;
|
||||
+
|
||||
+ spin_lock_bh(&ab->base_lock);
|
||||
+ peer = ath11k_peer_find_by_addr(ab, sta->addr);
|
||||
+ if (!peer) {
|
||||
+ ath11k_warn(ab, "failed to find peer for %pM\n", sta->addr);
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ peer_id = peer->peer_id;
|
||||
+ spin_unlock_bh(&ab->base_lock);
|
||||
+
|
||||
+ ret = ath11k_nss_ext_vdev_wds_4addr_allow(ap_vlan_arvif, peer_id);
|
||||
+ if (ret) {
|
||||
+ ath11k_warn(ab, "failed to set 4addr allow for %pM:%d\n",
|
||||
+ sta->addr, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
@@ -9976,6 +10195,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);
|
||||
+ } else if (ar->ab->nss.enabled &&
|
||||
+ vif->type == NL80211_IFTYPE_AP_VLAN &&
|
||||
+ !arsta->use_4addr_set) {
|
||||
+
|
||||
+ if (ar->state == ATH11K_STATE_RESTARTED) {
|
||||
+ /* During ieee80211_reconfig(), at this point, nss ext vdev peer is not
|
||||
+ * authorized. Hence ath11k_mac_cfg_dyn_vlan() will return error. We save
|
||||
+ * the state vars here and use it later once nss ext vdev is authorized
|
||||
+ * in ath11k_mac_op_set_key() */
|
||||
+ struct ath11k_dyn_vlan_cfg *ar_dyn_vlan_cfg;
|
||||
+ ar_dyn_vlan_cfg = kzalloc(sizeof(*ar_dyn_vlan_cfg), GFP_ATOMIC);
|
||||
+
|
||||
+ if (!ar_dyn_vlan_cfg) {
|
||||
+ ath11k_warn(ar->ab, "failed to save state for dynamic AP_VLAN configuration (%d)",
|
||||
+ -ENOSPC);
|
||||
+ } else {
|
||||
+ INIT_LIST_HEAD(&ar_dyn_vlan_cfg->cfg_list);
|
||||
+ ar_dyn_vlan_cfg->arvif = arvif;
|
||||
+ ar_dyn_vlan_cfg->sta = sta;
|
||||
+ /* save it to arvif (AP_VLAN) list */
|
||||
+ list_add_tail(&ar_dyn_vlan_cfg->cfg_list, &arvif->dyn_vlan_cfg);
|
||||
+ }
|
||||
+ } else {
|
||||
+ ret = ath11k_mac_cfg_dyn_vlan(ar->ab, arvif, sta);
|
||||
+ if (ret)
|
||||
+ ath11k_warn(ar->ab, "failed to cfg dyn vlan for peer %pM: %d\n",
|
||||
+ sta->addr, ret);
|
||||
+ }
|
||||
}
|
||||
|
||||
if (!ret &&
|
||||
@@ -10590,8 +10837,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) {
|
||||
ieee80211_hw_set(ar->hw, SUPPORTS_NSS_OFFLOAD);
|
||||
+ wiphy_ext_feature_set(ar->hw->wiphy,
|
||||
+ NL80211_EXT_FEATURE_VLAN_OFFLOAD);
|
||||
+ }
|
||||
|
||||
ret = ieee80211_register_hw(ar->hw);
|
||||
if (ret) {
|
||||
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
@@ -1984,6 +1984,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;
|
||||
+ cmd->group_key_id = arg->group_key_idx;
|
||||
|
||||
if (arg->key_rsc_counter)
|
||||
memcpy(&cmd->key_rsc_counter, &arg->key_rsc_counter,
|
||||
@@ -4323,6 +4324,7 @@ ath11k_wmi_copy_resource_config(struct w
|
||||
wmi_cfg->flags2 = WMI_RSRC_CFG_FLAG2_CALC_NEXT_DTIM_COUNT_SET;
|
||||
wmi_cfg->ema_max_vap_cnt = tg_cfg->ema_max_vap_cnt;
|
||||
wmi_cfg->ema_max_profile_period = tg_cfg->ema_max_profile_period;
|
||||
+ wmi_cfg->max_num_group_keys = tg_cfg->max_num_group_keys;
|
||||
}
|
||||
|
||||
static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi,
|
||||
@@ -4545,6 +4547,9 @@ int ath11k_wmi_cmd_init(struct ath11k_ba
|
||||
memset(&init_param, 0, sizeof(init_param));
|
||||
memset(&config, 0, sizeof(config));
|
||||
|
||||
+ if (ab->nss.enabled)
|
||||
+ config.max_num_group_keys = ATH11K_GROUP_KEYS_NUM_MAX;
|
||||
+
|
||||
ab->hw_params.hw_ops->wmi_init_config(ab, &config);
|
||||
|
||||
if (test_bit(WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT,
|
||||
--- a/drivers/net/wireless/ath/ath11k/wmi.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
|
||||
@@ -3755,6 +3755,7 @@ struct wmi_vdev_install_key_arg {
|
||||
u32 vdev_id;
|
||||
const u8 *macaddr;
|
||||
u32 key_idx;
|
||||
+ u32 group_key_idx;
|
||||
u32 key_flags;
|
||||
u32 key_cipher;
|
||||
u32 key_len;
|
||||
@@ -5815,6 +5816,7 @@ struct target_resource_config {
|
||||
u32 bpf_instruction_size;
|
||||
u32 max_bssid_rx_filters;
|
||||
u32 use_pdev_id;
|
||||
+ u32 max_num_group_keys;
|
||||
u32 peer_map_unmap_v2_support;
|
||||
u32 sched_params;
|
||||
u32 twt_ap_pdev_count;
|
||||
@ -0,0 +1,147 @@
|
||||
From 61342ee83df7fa0b90d5ece88e3f83dea426802c Mon Sep 17 00:00:00 2001
|
||||
From: P Praneesh <ppranees@codeaurora.org>
|
||||
Date: Mon, 14 Dec 2020 20:22:22 +0530
|
||||
Subject: [PATCH] ath11k: allocate dst ring descriptors from cacheable
|
||||
memory
|
||||
|
||||
tcl_data and reo_dst rings are currently being allocated
|
||||
using dma_allocate_coherent() which is non cachable.
|
||||
|
||||
Allocating ring memory from cacheable memory area
|
||||
allows cached descriptor access and prefetch next
|
||||
descriptors to optimize CPU usage during
|
||||
descriptor processing on NAPI.
|
||||
|
||||
Signed-off-by: Pradeep Kumar Chitrapu <pradeepc@codeaurora.org>
|
||||
Signed-off-by: Sriram R <srirrama@codeaurora.org>
|
||||
Signed-off-by: P Praneesh <ppranees@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/dp.c | 39 ++++++++++++++++++++++++++++++-----
|
||||
drivers/net/wireless/ath/ath11k/dp.h | 1 +
|
||||
drivers/net/wireless/ath/ath11k/hal.c | 33 ++++++++++++++++++++++++++---
|
||||
drivers/net/wireless/ath/ath11k/hal.h | 1 +
|
||||
4 files changed, 66 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
|
||||
@@ -769,6 +769,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];
|
||||
+ int valid_entries;
|
||||
u32 *desc;
|
||||
u32 msdu_id;
|
||||
u8 mac_id;
|
||||
@@ -777,9 +778,18 @@ void ath11k_dp_tx_completion_handler(str
|
||||
|
||||
ath11k_hal_srng_access_begin(ab, status_ring);
|
||||
|
||||
+ valid_entries = ath11k_hal_srng_dst_num_free(ab, status_ring, false);
|
||||
+ if (!valid_entries) {
|
||||
+ ath11k_hal_srng_access_end(ab, status_ring);
|
||||
+ spin_unlock_bh(&status_ring->lock);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ ath11k_hal_srng_dst_invalidate_entry(ab, status_ring, valid_entries);
|
||||
+
|
||||
while ((ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_head) !=
|
||||
tx_ring->tx_status_tail) &&
|
||||
- (desc = ath11k_hal_srng_dst_get_next_entry(ab, status_ring))) {
|
||||
+ (desc = ath11k_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 =
|
||||
--- a/drivers/net/wireless/ath/ath11k/hal.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/hal.c
|
||||
@@ -668,7 +668,8 @@ u32 *ath11k_hal_srng_dst_get_next_entry(
|
||||
|
||||
desc = srng->ring_base_vaddr + srng->u.dst_ring.tp;
|
||||
|
||||
- srng->u.dst_ring.tp += srng->entry_size;
|
||||
+ srng->u.dst_ring.tp = (srng->u.dst_ring.tp + srng->entry_size) %
|
||||
+ srng->ring_size;
|
||||
|
||||
/* wrap around to start of ring*/
|
||||
if (srng->u.dst_ring.tp == srng->ring_size)
|
||||
@@ -681,8 +682,63 @@ u32 *ath11k_hal_srng_dst_get_next_entry(
|
||||
return desc;
|
||||
}
|
||||
|
||||
+u32 *ath11k_hal_srng_dst_get_next_cache_entry(struct ath11k_base *ab,
|
||||
+ struct hal_srng *srng)
|
||||
+{
|
||||
+ u32 *desc,*desc_next;
|
||||
+ lockdep_assert_held(&srng->lock);
|
||||
+
|
||||
+ if (srng->u.dst_ring.tp == srng->u.dst_ring.cached_hp)
|
||||
+ return NULL;
|
||||
+
|
||||
+ desc = srng->ring_base_vaddr + srng->u.dst_ring.tp;
|
||||
+
|
||||
+ srng->u.dst_ring.tp = (srng->u.dst_ring.tp + srng->entry_size) %
|
||||
+ srng->ring_size;
|
||||
+
|
||||
+ /* Try to prefetch the next descriptor in the ring */
|
||||
+ if (srng->u.dst_ring.tp != srng->u.dst_ring.cached_hp) {
|
||||
+ /* prefetch only if desc is available */
|
||||
+ desc_next = srng->ring_base_vaddr + srng->u.dst_ring.tp;
|
||||
+ prefetch(desc_next);
|
||||
+ }
|
||||
+ return desc;
|
||||
+}
|
||||
+
|
||||
+void ath11k_hal_srng_dst_invalidate_entry(struct ath11k_base *ab,
|
||||
+ struct hal_srng *srng, int entries)
|
||||
+{
|
||||
+ u32 *desc;
|
||||
+ u32 tp, hp;
|
||||
+
|
||||
+ lockdep_assert_held(&srng->lock);
|
||||
+
|
||||
+ 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) {
|
||||
+ dma_sync_single_for_cpu(ab->dev, virt_to_phys(desc),
|
||||
+ entries * srng->entry_size * sizeof(u32),
|
||||
+ DMA_FROM_DEVICE);
|
||||
+ } else {
|
||||
+ entries = srng->ring_size - tp;
|
||||
+ dma_sync_single_for_cpu(ab->dev, virt_to_phys(desc),
|
||||
+ entries * sizeof(u32),
|
||||
+ DMA_FROM_DEVICE);
|
||||
+
|
||||
+ entries = hp;
|
||||
+ dma_sync_single_for_cpu(ab->dev, virt_to_phys(srng->ring_base_vaddr),
|
||||
+ entries * sizeof(u32),
|
||||
+ DMA_FROM_DEVICE);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
int ath11k_hal_srng_dst_num_free(struct ath11k_base *ab, struct hal_srng *srng,
|
||||
- bool sync_hw_ptr)
|
||||
+ bool sync_hw_ptr)
|
||||
{
|
||||
u32 tp, hp;
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/hal.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/hal.h
|
||||
@@ -946,8 +946,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);
|
||||
+u32 *ath11k_hal_srng_dst_get_next_cache_entry(struct ath11k_base *ab,
|
||||
+ struct hal_srng *srng);
|
||||
int ath11k_hal_srng_dst_num_free(struct ath11k_base *ab, struct hal_srng *srng,
|
||||
- bool sync_hw_ptr);
|
||||
+ bool sync_hw_ptr);
|
||||
+void ath11k_hal_srng_dst_invalidate_entry(struct ath11k_base *ab,
|
||||
+ struct hal_srng *srng, int entries);
|
||||
u32 *ath11k_hal_srng_src_peek(struct ath11k_base *ab, struct hal_srng *srng);
|
||||
u32 *ath11k_hal_srng_src_next_peek(struct ath11k_base *ab,
|
||||
struct hal_srng *srng);
|
||||
@ -0,0 +1,442 @@
|
||||
From 594992a7ef169aa406e7fc025df2455af5d226be Mon Sep 17 00:00:00 2001
|
||||
From: P Praneesh <ppranees@codeaurora.org>
|
||||
Date: Tue, 15 Dec 2020 10:31:30 +0530
|
||||
Subject: [PATCH] ath11k: Allow fast rx by bypassing stats update
|
||||
|
||||
Add a provision to disable stats and enable fast rx support
|
||||
for a peer when it is connected to an AP with ethernet decap support.
|
||||
All valid IP packets are directly passed to the net core stack
|
||||
bypassing mac80211 stats update
|
||||
|
||||
Signed-off-by: Sriram R <srirrama@codeaurora.org>
|
||||
Signed-off-by: P Praneesh <ppranees@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/core.h | 2
|
||||
drivers/net/wireless/ath/ath11k/debugfs.c | 75 ++++++++++++++++++
|
||||
drivers/net/wireless/ath/ath11k/dp_rx.c | 119 +++++++++++++++++++++++++++---
|
||||
drivers/net/wireless/ath/ath11k/hw.c | 22 +++++
|
||||
drivers/net/wireless/ath/ath11k/hw.h | 1
|
||||
drivers/net/wireless/ath/ath11k/mac.c | 8 ++
|
||||
6 files changed, 218 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/core.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
||||
@@ -149,6 +149,7 @@ struct ath11k_skb_rxcb {
|
||||
u8 tid;
|
||||
u16 peer_id;
|
||||
u16 seq_no;
|
||||
+ struct napi_struct *napi;
|
||||
};
|
||||
|
||||
enum ath11k_hw_rev {
|
||||
@@ -1139,6 +1140,7 @@ struct ath11k_base {
|
||||
u32 max_ast_index;
|
||||
u32 num_ast_entries;
|
||||
|
||||
+ bool stats_disable;
|
||||
/* must be last */
|
||||
u8 drv_priv[] __aligned(sizeof(void *));
|
||||
};
|
||||
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
|
||||
@@ -974,6 +974,79 @@ static const struct file_operations fops
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
+static void ath11k_debug_config_mon_status(struct ath11k *ar, bool enable)
|
||||
+{
|
||||
+ struct htt_rx_ring_tlv_filter tlv_filter = {0};
|
||||
+ struct ath11k_base *ab = ar->ab;
|
||||
+ int i;
|
||||
+ u32 ring_id;
|
||||
+
|
||||
+ if (enable)
|
||||
+ tlv_filter = ath11k_mac_mon_status_filter_default;
|
||||
+
|
||||
+ for (i = 0; i < ab->hw_params.num_rxdma_per_pdev; i++) {
|
||||
+ ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
|
||||
+ ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id,
|
||||
+ ar->dp.mac_id + i,
|
||||
+ HAL_RXDMA_MONITOR_STATUS,
|
||||
+ DP_RX_BUFFER_SIZE,
|
||||
+ &tlv_filter);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static ssize_t ath11k_write_stats_disable(struct file *file,
|
||||
+ const char __user *user_buf,
|
||||
+ size_t count, loff_t *ppos)
|
||||
+{
|
||||
+ struct ath11k_base *ab = file->private_data;
|
||||
+ struct ath11k_pdev *pdev;
|
||||
+ bool disable;
|
||||
+ int ret, i, radioup = 0;
|
||||
+ u32 mask = 0;
|
||||
+
|
||||
+ for (i = 0; i < ab->num_radios; i++) {
|
||||
+ pdev = &ab->pdevs[i];
|
||||
+ if (pdev && pdev->ar) {
|
||||
+ radioup = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (radioup == 0) {
|
||||
+ ath11k_err(ab, "radio is not up\n");
|
||||
+ ret = -ENETDOWN;
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ if (kstrtobool_from_user(user_buf, count, &disable))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (disable != ab->stats_disable) {
|
||||
+ ab->stats_disable = disable;
|
||||
+ for (i = 0; i < ab->num_radios; i++) {
|
||||
+ pdev = &ab->pdevs[i];
|
||||
+ if (pdev && pdev->ar) {
|
||||
+ ath11k_debug_config_mon_status(pdev->ar, !disable);
|
||||
+
|
||||
+ if (!disable)
|
||||
+ mask = HTT_PPDU_STATS_TAG_DEFAULT;
|
||||
+
|
||||
+ ath11k_dp_tx_htt_h2t_ppdu_stats_req(pdev->ar, mask);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ret = count;
|
||||
+
|
||||
+exit:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static const struct file_operations fops_soc_stats_disable = {
|
||||
+ .open = simple_open,
|
||||
+ .write = ath11k_write_stats_disable,
|
||||
+};
|
||||
+
|
||||
int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
|
||||
{
|
||||
if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
|
||||
@@ -1023,6 +1096,8 @@ int ath11k_debugfs_soc_create(struct ath
|
||||
ret = PTR_ERR(ab->debugfs_soc);
|
||||
goto out;
|
||||
}
|
||||
+ debugfs_create_file("stats_disable", 0600, ab->debugfs_soc, ab,
|
||||
+ &fops_soc_stats_disable);
|
||||
|
||||
ret = 0;
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
|
||||
@@ -341,6 +341,12 @@ static int ath11k_dp_purge_mon_ring(stru
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
+static inline u8 ath11k_dp_rx_h_msdu_start_ip_valid(struct ath11k_base *ab,
|
||||
+ struct hal_rx_desc *desc)
|
||||
+{
|
||||
+ return ab->hw_params.hw_ops->rx_desc_get_ip_valid(desc);
|
||||
+}
|
||||
+
|
||||
/* Returns number of Rx buffers replenished */
|
||||
int ath11k_dp_rxbufs_replenish(struct ath11k_base *ab, int mac_id,
|
||||
struct dp_rxdma_ring *rx_ring,
|
||||
@@ -1665,7 +1671,7 @@ int ath11k_dp_htt_tlv_iter(struct ath11k
|
||||
len -= sizeof(*tlv);
|
||||
|
||||
if (tlv_len > len) {
|
||||
- ath11k_err(ab, "htt tlv parse failure of tag %hhu at byte %zd (%zu bytes left, %hhu expected)\n",
|
||||
+ ath11k_err(ab, "htt tlv parse failure of tag %hu at byte %zd (%zu bytes left, %hu expected)\n",
|
||||
tlv_tag, ptr - begin, len, tlv_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -2454,10 +2460,60 @@ ath11k_dp_rx_h_find_peer(struct ath11k_b
|
||||
return peer;
|
||||
}
|
||||
|
||||
+static bool ath11k_dp_rx_check_fast_rx(struct ath11k *ar,
|
||||
+ struct sk_buff *msdu,
|
||||
+ struct hal_rx_desc *rx_desc,
|
||||
+ struct ath11k_peer *peer)
|
||||
+{
|
||||
+ struct ethhdr *ehdr;
|
||||
+ struct ath11k_peer *f_peer;
|
||||
+ struct ath11k_skb_rxcb *rxcb;
|
||||
+ u8 decap;
|
||||
+
|
||||
+ lockdep_assert_held(&ar->ab->base_lock);
|
||||
+
|
||||
+ decap = ath11k_dp_rx_h_msdu_start_decap_type(ar->ab, rx_desc);
|
||||
+ rxcb = ATH11K_SKB_RXCB(msdu);
|
||||
+
|
||||
+ if (!ar->ab->stats_disable ||
|
||||
+ decap != DP_RX_DECAP_TYPE_ETHERNET2_DIX ||
|
||||
+ peer->vif->type != NL80211_IFTYPE_AP)
|
||||
+ return false;
|
||||
+
|
||||
+ /* mcbc packets go through mac80211 for PN validation */
|
||||
+ if (rxcb->is_mcbc)
|
||||
+ return false;
|
||||
+
|
||||
+ if (!peer->is_authorized)
|
||||
+ return false;
|
||||
+
|
||||
+ if (!ath11k_dp_rx_h_msdu_start_ip_valid(ar->ab, rx_desc))
|
||||
+ return false;
|
||||
+
|
||||
+ /* fast rx is supported only on ethernet decap, so
|
||||
+ * we can directly gfet the ethernet header
|
||||
+ */
|
||||
+ ehdr = (struct ethhdr *)msdu->data;
|
||||
+
|
||||
+ /* requires rebroadcast from mac80211 */
|
||||
+ if (is_multicast_ether_addr(ehdr->h_dest))
|
||||
+ return false;
|
||||
+
|
||||
+ /* check if the msdu needs to be bridged to our connected peer */
|
||||
+ f_peer = ath11k_peer_find_by_addr(ar->ab, ehdr->h_dest);
|
||||
+
|
||||
+ if (f_peer && f_peer != peer)
|
||||
+ return false;
|
||||
+
|
||||
+ /* allow direct rx */
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
static void ath11k_dp_rx_h_mpdu(struct ath11k *ar,
|
||||
struct sk_buff *msdu,
|
||||
struct hal_rx_desc *rx_desc,
|
||||
- struct ieee80211_rx_status *rx_status)
|
||||
+ struct ieee80211_rx_status *rx_status,
|
||||
+ bool *fast_rx)
|
||||
{
|
||||
bool fill_crypto_hdr;
|
||||
enum hal_encrypt_type enctype;
|
||||
@@ -2468,9 +2524,13 @@ static void ath11k_dp_rx_h_mpdu(struct a
|
||||
struct rx_attention *rx_attention;
|
||||
u32 err_bitmap;
|
||||
|
||||
+ struct wireless_dev *wdev = NULL;
|
||||
+ struct ath11k_sta *arsta = NULL;
|
||||
+
|
||||
/* 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);
|
||||
+ if (!ar->ab->nss.enabled)
|
||||
+ fill_crypto_hdr = ath11k_dp_rx_h_attn_is_mcbc(ar->ab, rx_desc);
|
||||
rxcb->is_mcbc = fill_crypto_hdr;
|
||||
|
||||
if (rxcb->is_mcbc) {
|
||||
@@ -2481,6 +2541,26 @@ 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) {
|
||||
+ /* If the pkt is a valid IP packet and peer supports
|
||||
+ * fast rx, deliver directly to net, also note that
|
||||
+ * pkts with crypto error are not expected to arrive in this
|
||||
+ * path, so its safe to skip checking errors here */
|
||||
+ if (*fast_rx &&
|
||||
+ ath11k_dp_rx_check_fast_rx(ar, msdu, rx_desc, peer)) {
|
||||
+ wdev = ieee80211_vif_to_wdev(peer->vif);
|
||||
+ if (wdev) {
|
||||
+ spin_unlock_bh(&ar->ab->base_lock);
|
||||
+ ath11k_dp_rx_h_csum_offload(ar, msdu);
|
||||
+ msdu->dev = wdev->netdev;
|
||||
+ msdu->protocol = eth_type_trans(msdu, msdu->dev);
|
||||
+ napi_gro_receive(rxcb->napi, msdu);
|
||||
+ if (peer->sta)
|
||||
+ arsta =
|
||||
+ (struct ath11k_sta *)peer->sta->drv_priv;
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (rxcb->is_mcbc)
|
||||
enctype = peer->sec_type_grp;
|
||||
else
|
||||
@@ -2490,6 +2570,8 @@ static void ath11k_dp_rx_h_mpdu(struct a
|
||||
}
|
||||
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)
|
||||
@@ -2731,7 +2813,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,
|
||||
- struct ieee80211_rx_status *rx_status)
|
||||
+ struct ieee80211_rx_status *rx_status,
|
||||
+ bool *fast_rx)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct hal_rx_desc *rx_desc, *lrx_desc;
|
||||
@@ -2798,8 +2881,13 @@ static int ath11k_dp_rx_process_msdu(str
|
||||
}
|
||||
}
|
||||
|
||||
+ ath11k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_status, fast_rx);
|
||||
+ if (*fast_rx) {
|
||||
+ ab->soc_stats.invalid_rbm++;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
ath11k_dp_rx_h_ppdu(ar, rx_desc, rx_status);
|
||||
- ath11k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_status);
|
||||
|
||||
rx_status->flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED;
|
||||
|
||||
@@ -2814,10 +2902,12 @@ static void ath11k_dp_rx_process_receive
|
||||
struct sk_buff_head *msdu_list,
|
||||
int mac_id)
|
||||
{
|
||||
+ struct ath11k_skb_rxcb *rxcb;
|
||||
struct sk_buff *msdu;
|
||||
struct ath11k *ar;
|
||||
struct ieee80211_rx_status rx_status = {0};
|
||||
int ret;
|
||||
+ bool fast_rx;
|
||||
|
||||
if (skb_queue_empty(msdu_list))
|
||||
return;
|
||||
@@ -2834,7 +2924,12 @@ static void ath11k_dp_rx_process_receive
|
||||
}
|
||||
|
||||
while ((msdu = __skb_dequeue(msdu_list))) {
|
||||
- ret = ath11k_dp_rx_process_msdu(ar, msdu, msdu_list, &rx_status);
|
||||
+ rxcb = ATH11K_SKB_RXCB(msdu);
|
||||
+ /* Enable fast rx by default, the value will cahnge based on peer cap
|
||||
+ * and packet type */
|
||||
+ fast_rx = true;
|
||||
+ rxcb->napi = napi;
|
||||
+ ret = ath11k_dp_rx_process_msdu(ar, msdu, msdu_list, &rx_status, &fast_rx);
|
||||
if (unlikely(ret)) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_DATA,
|
||||
"Unable to process msdu %d", ret);
|
||||
@@ -2842,7 +2937,10 @@ static void ath11k_dp_rx_process_receive
|
||||
continue;
|
||||
}
|
||||
|
||||
- ath11k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_status);
|
||||
+ /* msdu is already delivered directectly */
|
||||
+ if (!fast_rx)
|
||||
+ ath11k_dp_rx_deliver_msdu(ar, napi, msdu, &rx_status);
|
||||
+
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2851,11 +2949,12 @@ void ath11k_dp_rx_from_nss(struct ath11k
|
||||
{
|
||||
struct ieee80211_rx_status rx_status = {0};
|
||||
struct ath11k_skb_rxcb *rxcb;
|
||||
+ bool fast_rx = false;
|
||||
|
||||
rxcb = ATH11K_SKB_RXCB(msdu);
|
||||
|
||||
ath11k_dp_rx_h_ppdu(ar, rxcb->rx_desc, &rx_status);
|
||||
- ath11k_dp_rx_h_mpdu(ar, msdu, rxcb->rx_desc, &rx_status);
|
||||
+ ath11k_dp_rx_h_mpdu(ar, msdu, rxcb->rx_desc, &rx_status, &fast_rx);
|
||||
|
||||
rx_status.flag |= RX_FLAG_SKIP_MONITOR | RX_FLAG_DUP_VALIDATED;
|
||||
|
||||
@@ -4387,6 +4486,7 @@ static int ath11k_dp_rx_h_null_q_desc(st
|
||||
struct ieee80211_rx_status *status,
|
||||
struct sk_buff_head *msdu_list)
|
||||
{
|
||||
+ bool fast_rx;
|
||||
u16 msdu_len;
|
||||
struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data;
|
||||
struct rx_attention *rx_attention;
|
||||
@@ -4436,7 +4536,8 @@ static int ath11k_dp_rx_h_null_q_desc(st
|
||||
}
|
||||
ath11k_dp_rx_h_ppdu(ar, desc, status);
|
||||
|
||||
- ath11k_dp_rx_h_mpdu(ar, msdu, desc, status);
|
||||
+ fast_rx = false;
|
||||
+ ath11k_dp_rx_h_mpdu(ar, msdu, desc, status, &fast_rx);
|
||||
|
||||
rxcb->tid = ath11k_dp_rx_h_mpdu_start_tid(ar->ab, desc);
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/hw.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/hw.c
|
||||
@@ -293,6 +293,16 @@ static bool ath11k_hw_ipq8074_rx_desc_ge
|
||||
__le32_to_cpu(desc->u.ipq8074.msdu_start.info2));
|
||||
}
|
||||
|
||||
+static u8 ath11k_hw_ipq8074_rx_desc_get_ip_valid(struct hal_rx_desc *desc)
|
||||
+{
|
||||
+ bool ipv4, ipv6;
|
||||
+ ipv4 = FIELD_GET(RX_MSDU_START_INFO2_IPV4,
|
||||
+ __le32_to_cpu(desc->u.ipq8074.msdu_start.info2));
|
||||
+ ipv6 = FIELD_GET(RX_MSDU_START_INFO2_IPV6,
|
||||
+ __le32_to_cpu(desc->u.ipq8074.msdu_start.info2));
|
||||
+ return (ipv4 || ipv6);
|
||||
+}
|
||||
+
|
||||
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,
|
||||
@@ -470,6 +480,16 @@ static bool ath11k_hw_qcn9074_rx_desc_ge
|
||||
__le32_to_cpu(desc->u.qcn9074.msdu_start.info2));
|
||||
}
|
||||
|
||||
+static u8 ath11k_hw_qcn9074_rx_desc_get_ip_valid(struct hal_rx_desc *desc)
|
||||
+{
|
||||
+ bool ipv4 , ipv6;
|
||||
+ ipv4 = FIELD_GET(RX_MSDU_START_INFO2_IPV4,
|
||||
+ __le32_to_cpu(desc->u.qcn9074.msdu_start.info2));
|
||||
+ ipv6 = FIELD_GET(RX_MSDU_START_INFO2_IPV6,
|
||||
+ __le32_to_cpu(desc->u.qcn9074.msdu_start.info2));
|
||||
+ return (ipv4 || ipv6);
|
||||
+}
|
||||
+
|
||||
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,
|
||||
@@ -1025,6 +1045,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,
|
||||
+ .rx_desc_get_ip_valid = ath11k_hw_ipq8074_rx_desc_get_ip_valid,
|
||||
.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,
|
||||
@@ -1189,6 +1210,7 @@ const struct ath11k_hw_ops ipq5018_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_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,
|
||||
--- a/drivers/net/wireless/ath/ath11k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/hw.h
|
||||
@@ -267,6 +267,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);
|
||||
+ u8 (*rx_desc_get_ip_valid)(struct hal_rx_desc *desc);
|
||||
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);
|
||||
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
||||
@@ -10249,6 +10249,14 @@ static int ath11k_mac_op_sta_state(struc
|
||||
}
|
||||
} else if (old_state == IEEE80211_STA_AUTHORIZED &&
|
||||
new_state == IEEE80211_STA_ASSOC) {
|
||||
+
|
||||
+ spin_lock_bh(&ar->ab->base_lock);
|
||||
+ peer = ath11k_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_AUTHORIZED &&
|
||||
+ new_state == IEEE80211_STA_ASSOC) {
|
||||
spin_lock_bh(&ar->ab->base_lock);
|
||||
|
||||
peer = ath11k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
|
||||
@ -0,0 +1,633 @@
|
||||
From a19b1279d75dd1306c6eac291e985657f988780c Mon Sep 17 00:00:00 2001
|
||||
From: P Praneesh <ppranees@codeaurora.org>
|
||||
Date: Thu, 7 Jan 2021 16:32:30 +0530
|
||||
Subject: [PATCH] ath11k: dp_tx perf improvements
|
||||
|
||||
Contains below changes,
|
||||
1. Add branch prediction in tx path
|
||||
2. Allow fast tx completion by freeing skb when stats is disabled.
|
||||
3. Remove mod operator overhead for dst ring access to avoid(to be profiled)
|
||||
4. Lockless tcl ring usage since rings are selected per cpu
|
||||
|
||||
Sample stats disable command:
|
||||
echo 1 > /sys/kernel/debug/ath11k/qcn9000\ hw1.0_0000\:01\:00.0/stats_disable
|
||||
echo 1 > /sys/kernel/debug/ath11k/ipq8074\ hw2.0/stats_disable
|
||||
|
||||
Signed-off-by: Sriram R <srirrama@codeaurora.org>
|
||||
Signed-off-by: P Praneesh <ppranees@codeaurora.org>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/core.h | 1 +
|
||||
drivers/net/wireless/ath/ath11k/dp.c | 7 +-
|
||||
drivers/net/wireless/ath/ath11k/dp_tx.c | 118 ++++++++++++++++++--------------
|
||||
drivers/net/wireless/ath/ath11k/dp_tx.h | 2 +
|
||||
drivers/net/wireless/ath/ath11k/hal.c | 9 ++-
|
||||
drivers/net/wireless/ath/ath11k/mac.c | 9 ++-
|
||||
6 files changed, 88 insertions(+), 58 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/core.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
||||
@@ -121,6 +121,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),
|
||||
+ ATH11K_SKB_TX_STATUS = BIT(2),
|
||||
};
|
||||
|
||||
struct ath11k_skb_cb {
|
||||
@@ -934,10 +935,13 @@ 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];
|
||||
+ /* TCL Ring IDR unavailable */
|
||||
+ u32 idr_na[DP_TCL_NUM_RING_MAX];
|
||||
/* Other failures during dp_tx due to mem allocation failure
|
||||
* idr unavailable etc.
|
||||
*/
|
||||
atomic_t misc_fail;
|
||||
+ atomic_t max_fail;
|
||||
/* Tx failures due to NSS Tx error status */
|
||||
atomic_t nss_tx_fail;
|
||||
};
|
||||
--- a/drivers/net/wireless/ath/ath11k/dp.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/dp.c
|
||||
@@ -372,7 +372,7 @@ void ath11k_dp_stop_shadow_timers(struct
|
||||
if (!ab->hw_params.supports_shadow_regs)
|
||||
return;
|
||||
|
||||
- for (i = 0; i < ab->hw_params.max_tx_ring; i++)
|
||||
+ for (i = 0; i < DP_TCL_NUM_RING_MAX; i++)
|
||||
ath11k_dp_shadow_stop_timer(ab, &ab->dp.tx_ring_timer[i]);
|
||||
|
||||
ath11k_dp_shadow_stop_timer(ab, &ab->dp.reo_cmd_timer);
|
||||
@@ -441,7 +441,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);
|
||||
- for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
|
||||
+ for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) {
|
||||
ath11k_dp_srng_cleanup(ab, &dp->tx_ring[i].tcl_data_ring);
|
||||
ath11k_dp_srng_cleanup(ab, &dp->tx_ring[i].tcl_comp_ring);
|
||||
}
|
||||
@@ -477,6 +477,11 @@ static int ath11k_dp_srng_common_setup(s
|
||||
goto err;
|
||||
}
|
||||
|
||||
+ if (ab->hw_params.max_tx_ring > DP_TCL_NUM_RING_MAX) {
|
||||
+ srng = &ab->hal.srng_list[dp->tcl_cmd_ring.ring_id];
|
||||
+ ath11k_hal_tx_init_data_ring(ab, srng, HAL_TCL_CMD);
|
||||
+ }
|
||||
+
|
||||
ret = ath11k_dp_srng_setup(ab, &dp->tcl_status_ring, HAL_TCL_STATUS,
|
||||
0, 0, DP_TCL_STATUS_RING_SIZE);
|
||||
if (ret) {
|
||||
@@ -484,7 +489,7 @@ static int ath11k_dp_srng_common_setup(s
|
||||
goto err;
|
||||
}
|
||||
|
||||
- for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
|
||||
+ for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) {
|
||||
tcl_num = ab->hw_params.hal_params->tcl2wbm_rbm_map[i].tcl_ring_num;
|
||||
wbm_num = ab->hw_params.hal_params->tcl2wbm_rbm_map[i].wbm_ring_num;
|
||||
|
||||
@@ -507,7 +512,7 @@ static int ath11k_dp_srng_common_setup(s
|
||||
}
|
||||
|
||||
srng = &ab->hal.srng_list[dp->tx_ring[i].tcl_data_ring.ring_id];
|
||||
- ath11k_hal_tx_init_data_ring(ab, srng);
|
||||
+ ath11k_hal_tx_init_data_ring(ab, srng, HAL_TCL_DATA);
|
||||
|
||||
ath11k_dp_shadow_init_timer(ab, &dp->tx_ring_timer[i],
|
||||
ATH11K_SHADOW_DP_TIMER_INTERVAL,
|
||||
@@ -1121,7 +1126,7 @@ void ath11k_dp_free(struct ath11k_base *
|
||||
|
||||
ath11k_dp_reo_cmd_list_cleanup(ab);
|
||||
|
||||
- for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
|
||||
+ for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) {
|
||||
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);
|
||||
@@ -1172,7 +1177,7 @@ int ath11k_dp_alloc(struct ath11k_base *
|
||||
|
||||
size = sizeof(struct hal_wbm_release_ring) * DP_TX_COMP_RING_SIZE;
|
||||
|
||||
- for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
|
||||
+ for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) {
|
||||
idr_init(&dp->tx_ring[i].txbuf_idr);
|
||||
spin_lock_init(&dp->tx_ring[i].tx_idr_lock);
|
||||
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
|
||||
@@ -134,28 +134,34 @@ int ath11k_dp_tx(struct ath11k *ar, stru
|
||||
u32 ring_selector = 0;
|
||||
u8 ring_map = 0;
|
||||
bool tcl_ring_retry, is_diff_encap = false;
|
||||
- u8 align_pad, htt_meta_size = 0;
|
||||
-
|
||||
- if (unlikely(test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags)))
|
||||
- return -ESHUTDOWN;
|
||||
+ u8 align_pad, htt_meta_size = 0, max_tx_ring, tcl_ring_id, ring_id;
|
||||
|
||||
if (unlikely(!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
|
||||
!ieee80211_is_data(hdr->frame_control)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
- pool_id = skb_get_queue_mapping(skb) & (ATH11K_HW_MAX_QUEUES - 1);
|
||||
+ max_tx_ring = ab->hw_params.max_tx_ring;
|
||||
|
||||
- ring_selector = ab->hw_params.hw_ops->get_ring_selector(skb);
|
||||
+#ifdef CPTCFG_ATH11K_MEM_PROFILE_512M
|
||||
+ if (unlikely(atomic_read(&ab->num_max_allowed) > DP_TX_COMP_MAX_ALLOWED)) {
|
||||
+ atomic_inc(&ab->soc_stats.tx_err.max_fail);
|
||||
+ return -ENOSPC;
|
||||
+ }
|
||||
+#endif
|
||||
+ ring_selector = smp_processor_id();;
|
||||
+ pool_id = ring_selector;
|
||||
|
||||
tcl_ring_sel:
|
||||
tcl_ring_retry = false;
|
||||
|
||||
- ti.ring_id = ring_selector % ab->hw_params.max_tx_ring;
|
||||
- ti.rbm_id = ab->hw_params.hal_params->tcl2wbm_rbm_map[ti.ring_id].rbm_id;
|
||||
+ ring_id = ring_selector % max_tx_ring;
|
||||
+ tcl_ring_id = (ring_id == DP_TCL_NUM_RING_MAX) ?
|
||||
+ DP_TCL_NUM_RING_MAX - 1 : ring_id;
|
||||
|
||||
- ring_map |= BIT(ti.ring_id);
|
||||
+ ring_map |= BIT(ring_id);
|
||||
|
||||
- tx_ring = &dp->tx_ring[ti.ring_id];
|
||||
+ ti.buf_id = tcl_ring_id + HAL_RX_BUF_RBM_SW0_BM;
|
||||
+ tx_ring = &dp->tx_ring[tcl_ring_id];
|
||||
|
||||
spin_lock_bh(&tx_ring->tx_idr_lock);
|
||||
ret = idr_alloc(&tx_ring->txbuf_idr, skb, 0,
|
||||
@@ -163,9 +169,9 @@ tcl_ring_sel:
|
||||
spin_unlock_bh(&tx_ring->tx_idr_lock);
|
||||
|
||||
if (unlikely(ret < 0)) {
|
||||
- if (ring_map == (BIT(ab->hw_params.max_tx_ring) - 1) ||
|
||||
+ if (ring_map == (BIT(max_tx_ring) - 1) ||
|
||||
!ab->hw_params.tcl_ring_retry) {
|
||||
- atomic_inc(&ab->soc_stats.tx_err.misc_fail);
|
||||
+ ab->soc_stats.tx_err.idr_na[tcl_ring_id]++;
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
@@ -276,6 +282,11 @@ tcl_ring_sel:
|
||||
ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN;
|
||||
}
|
||||
|
||||
+ ti.data_len = skb->len - ti.pkt_offset;
|
||||
+ skb_cb->pkt_offset = ti.pkt_offset;
|
||||
+ skb_cb->vif = arvif->vif;
|
||||
+ skb_cb->ar = ar;
|
||||
+
|
||||
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);
|
||||
@@ -284,13 +295,13 @@ tcl_ring_sel:
|
||||
goto fail_remove_idr;
|
||||
}
|
||||
|
||||
- ti.data_len = skb->len - ti.pkt_offset;
|
||||
- skb_cb->pkt_offset = ti.pkt_offset;
|
||||
skb_cb->paddr = ti.paddr;
|
||||
- skb_cb->vif = arvif->vif;
|
||||
- skb_cb->ar = ar;
|
||||
|
||||
- hal_ring_id = tx_ring->tcl_data_ring.ring_id;
|
||||
+ if (ring_id == DP_TCL_NUM_RING_MAX)
|
||||
+ hal_ring_id = dp->tcl_cmd_ring.ring_id;
|
||||
+ else
|
||||
+ 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);
|
||||
@@ -303,7 +314,7 @@ tcl_ring_sel:
|
||||
* desc because the desc is directly enqueued onto hw queue.
|
||||
*/
|
||||
ath11k_hal_srng_access_end(ab, tcl_ring);
|
||||
- ab->soc_stats.tx_err.desc_na[ti.ring_id]++;
|
||||
+ ab->soc_stats.tx_err.desc_na[tcl_ring_id]++;
|
||||
spin_unlock_bh(&tcl_ring->lock);
|
||||
ret = -ENOMEM;
|
||||
|
||||
@@ -312,8 +323,8 @@ tcl_ring_sel:
|
||||
* checking this ring earlier for each pkt tx.
|
||||
* Restart ring selection if some rings are not checked yet.
|
||||
*/
|
||||
- if (unlikely(ring_map != (BIT(ab->hw_params.max_tx_ring)) - 1) &&
|
||||
- ab->hw_params.tcl_ring_retry && ab->hw_params.max_tx_ring > 1) {
|
||||
+ if (unlikely(ring_map != (BIT(max_tx_ring)) - 1) &&
|
||||
+ ab->hw_params.tcl_ring_retry && max_tx_ring > 1) {
|
||||
tcl_ring_retry = true;
|
||||
ring_selector++;
|
||||
}
|
||||
@@ -324,17 +335,17 @@ tcl_ring_sel:
|
||||
ath11k_hal_tx_cmd_desc_setup(ab, hal_tcl_desc +
|
||||
sizeof(struct hal_tlv_hdr), &ti);
|
||||
|
||||
+ atomic_inc(&ar->dp.num_tx_pending);
|
||||
+ atomic_inc(&ab->num_max_allowed);
|
||||
ath11k_hal_srng_access_end(ab, tcl_ring);
|
||||
|
||||
- ath11k_dp_shadow_start_timer(ab, tcl_ring, &dp->tx_ring_timer[ti.ring_id]);
|
||||
+ ath11k_dp_shadow_start_timer(ab, tcl_ring, &dp->tx_ring_timer[ti.buf_id]);
|
||||
|
||||
spin_unlock_bh(&tcl_ring->lock);
|
||||
|
||||
ath11k_dbg_dump(ab, ATH11K_DBG_DP_TX, NULL, "dp tx msdu: ",
|
||||
skb->data, skb->len);
|
||||
|
||||
- atomic_inc(&ar->dp.num_tx_pending);
|
||||
- atomic_inc(&ab->num_max_allowed);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -381,7 +392,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);
|
||||
- atomic_dec(&ab->num_max_allowed);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -395,6 +405,7 @@ ath11k_dp_tx_htt_tx_complete_buf(struct
|
||||
struct ath11k_skb_cb *skb_cb;
|
||||
struct ath11k *ar;
|
||||
struct ath11k_peer *peer;
|
||||
+ u8 flags = 0;
|
||||
|
||||
spin_lock(&tx_ring->tx_idr_lock);
|
||||
msdu = idr_remove(&tx_ring->txbuf_idr, ts->msdu_id);
|
||||
@@ -413,10 +424,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);
|
||||
- atomic_dec(&ab->num_max_allowed);
|
||||
|
||||
dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
|
||||
|
||||
+ flags = skb_cb->flags;
|
||||
+
|
||||
+ /* Free skb here if stats is disabled */
|
||||
+ if (ab->stats_disable && !(flags & ATH11K_SKB_TX_STATUS)) {
|
||||
+ if (msdu->destructor) {
|
||||
+ msdu->wifi_acked_valid = 1;
|
||||
+ msdu->wifi_acked = ts->acked;
|
||||
+ }
|
||||
+ if (skb_has_frag_list(msdu)) {
|
||||
+ kfree_skb_list(skb_shinfo(msdu)->frag_list);
|
||||
+ skb_shinfo(msdu)->frag_list = NULL;
|
||||
+ }
|
||||
+ dev_kfree_skb(msdu);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (unlikely(!skb_cb->vif)) {
|
||||
+ dev_kfree_skb_any(msdu);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (!skb_cb->vif) {
|
||||
ieee80211_free_txskb(ar->hw, msdu);
|
||||
return;
|
||||
@@ -636,6 +667,7 @@ static void ath11k_dp_tx_complete_msdu(s
|
||||
struct ath11k_peer *peer;
|
||||
struct ath11k_sta *arsta;
|
||||
struct rate_info rate;
|
||||
+ u8 flags = 0;
|
||||
|
||||
if (WARN_ON_ONCE(ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)) {
|
||||
/* Must not happen */
|
||||
@@ -646,6 +678,20 @@ static void ath11k_dp_tx_complete_msdu(s
|
||||
|
||||
dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
|
||||
|
||||
+ /* Free skb here if stats is disabled */
|
||||
+ if (ab->stats_disable && !(flags & ATH11K_SKB_TX_STATUS)) {
|
||||
+ if (msdu->destructor) {
|
||||
+ msdu->wifi_acked_valid = 1;
|
||||
+ msdu->wifi_acked = ts->status == HAL_WBM_TQM_REL_REASON_FRAME_ACKED;
|
||||
+ }
|
||||
+ if (skb_has_frag_list(msdu)) {
|
||||
+ kfree_skb_list(skb_shinfo(msdu)->frag_list);
|
||||
+ skb_shinfo(msdu)->frag_list = NULL;
|
||||
+ }
|
||||
+ dev_kfree_skb(msdu);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (unlikely(!rcu_access_pointer(ab->pdevs_active[ar->pdev_idx]))) {
|
||||
ieee80211_free_txskb(ar->hw, msdu);
|
||||
return;
|
||||
@@ -704,7 +750,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);
|
||||
- if (!peer || !peer->sta) {
|
||||
+ if (unlikely(!peer || !peer->sta)) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_DATA,
|
||||
"dp_tx: failed to find the peer with peer_id %d\n",
|
||||
ts->peer_id);
|
||||
@@ -760,19 +806,36 @@ static inline void ath11k_dp_tx_status_p
|
||||
ts->rate_stats = 0;
|
||||
}
|
||||
|
||||
+static inline bool ath11k_dp_tx_completion_valid(struct hal_wbm_release_ring *desc)
|
||||
+{
|
||||
+ struct htt_tx_wbm_completion *status_desc;
|
||||
+
|
||||
+ if (FIELD_GET(HAL_WBM_RELEASE_INFO0_REL_SRC_MODULE, desc->info0) ==
|
||||
+ HAL_WBM_REL_SRC_MODULE_FW) {
|
||||
+ status_desc = ((struct htt_tx_wbm_completion *)desc) + HTT_TX_WBM_COMP_STATUS_OFFSET;
|
||||
+
|
||||
+ /* Dont consider HTT_TX_COMP_STATUS_MEC_NOTIFY */
|
||||
+ if (FIELD_GET(HTT_TX_WBM_COMP_INFO0_STATUS, status_desc->info0) ==
|
||||
+ HAL_WBM_REL_HTT_TX_COMP_STATUS_MEC_NOTIFY)
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id)
|
||||
{
|
||||
struct ath11k *ar;
|
||||
struct ath11k_dp *dp = &ab->dp;
|
||||
- int hal_ring_id = dp->tx_ring[ring_id].tcl_comp_ring.ring_id;
|
||||
+ 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;
|
||||
struct hal_tx_status ts = { 0 };
|
||||
struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id];
|
||||
int valid_entries;
|
||||
u32 *desc;
|
||||
- u32 msdu_id;
|
||||
+ u32 msdu_id, desc_id;
|
||||
u8 mac_id;
|
||||
+ struct hal_wbm_release_ring *tx_status;
|
||||
|
||||
spin_lock_bh(&status_ring->lock);
|
||||
|
||||
@@ -787,33 +850,27 @@ void ath11k_dp_tx_completion_handler(str
|
||||
|
||||
ath11k_hal_srng_dst_invalidate_entry(ab, status_ring, valid_entries);
|
||||
|
||||
- while ((ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_head) !=
|
||||
- tx_ring->tx_status_tail) &&
|
||||
- (desc = ath11k_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 =
|
||||
- ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_head);
|
||||
- }
|
||||
+ while ((desc = ath11k_hal_srng_dst_get_next_cache_entry(ab, status_ring))) {
|
||||
+ if (!ath11k_dp_tx_completion_valid((struct hal_wbm_release_ring *)desc))
|
||||
+ continue;
|
||||
|
||||
- if (unlikely((ath11k_hal_srng_dst_peek(ab, status_ring) != NULL) &&
|
||||
- (ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_head) ==
|
||||
- tx_ring->tx_status_tail))) {
|
||||
- /* TODO: Process pending tx_status messages when kfifo_is_full() */
|
||||
- ath11k_warn(ab, "Unable to process some of the tx_status ring desc because status_fifo is full\n");
|
||||
+ memcpy(&tx_ring->tx_status[count],
|
||||
+ desc, sizeof(struct hal_wbm_release_ring));
|
||||
+ count++;
|
||||
}
|
||||
|
||||
ath11k_hal_srng_access_end(ab, status_ring);
|
||||
|
||||
spin_unlock_bh(&status_ring->lock);
|
||||
|
||||
- while (ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_tail) != tx_ring->tx_status_head) {
|
||||
- struct hal_wbm_release_ring *tx_status;
|
||||
- u32 desc_id;
|
||||
-
|
||||
- tx_ring->tx_status_tail =
|
||||
- ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_tail);
|
||||
- tx_status = &tx_ring->tx_status[tx_ring->tx_status_tail];
|
||||
+ if (atomic_sub_return(count, &ab->num_max_allowed) < 0) {
|
||||
+ ath11k_warn(ab, "tx completion mismatch count %d ring id %d max_num %d\n",
|
||||
+ count, tx_ring->tcl_data_ring_id,
|
||||
+ atomic_read(&ab->num_max_allowed));
|
||||
+ }
|
||||
+
|
||||
+ while (count--) {
|
||||
+ tx_status = &tx_ring->tx_status[i++];
|
||||
ath11k_dp_tx_status_parse(ab, tx_status, &ts);
|
||||
|
||||
desc_id = FIELD_GET(BUFFER_ADDR_INFO1_SW_COOKIE,
|
||||
@@ -846,7 +903,6 @@ void ath11k_dp_tx_completion_handler(str
|
||||
wake_up(&ar->dp.tx_empty_waitq);
|
||||
|
||||
ath11k_dp_tx_complete_msdu(ar, msdu, &ts);
|
||||
- atomic_dec(&ab->num_max_allowed);
|
||||
}
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
||||
@@ -6487,12 +6487,22 @@ static void ath11k_mac_op_tx(struct ieee
|
||||
if (control->sta)
|
||||
arsta = ath11k_sta_to_arsta(control->sta);
|
||||
|
||||
+ /* 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 disabled.
|
||||
+ */
|
||||
+ if ((info->flags & (IEEE80211_TX_CTL_REQ_TX_STATUS | IEEE80211_TX_INTFL_NL80211_FRAME_TX)) ||
|
||||
+ info->status_data || vif->type == NL80211_IFTYPE_MESH_POINT ||
|
||||
+ test_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags))
|
||||
+ skb_cb->flags |= ATH11K_SKB_TX_STATUS;
|
||||
+
|
||||
if (ar->ab->nss.enabled)
|
||||
ret = ath11k_nss_tx(arvif, skb);
|
||||
else
|
||||
ret = ath11k_dp_tx(ar, arvif, arsta, skb);
|
||||
+
|
||||
if (unlikely(ret)) {
|
||||
- ath11k_warn(ar->ab, "failed to transmit frame %d\n", ret);
|
||||
+ if (!ar->ab->nss.enabled && ret != -ENOSPC && ret != -ENOMEM)
|
||||
+ ath11k_warn(ar->ab, "failed to transmit frame %d\n", ret);
|
||||
ieee80211_free_txskb(ar->hw, skb);
|
||||
return;
|
||||
}
|
||||
@@ -7460,7 +7470,7 @@ err_vdev_del:
|
||||
idr_for_each(&ar->txmgmt_idr,
|
||||
ath11k_mac_vif_txmgmt_idr_remove, vif);
|
||||
|
||||
- for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
|
||||
+ for (i = 0; i < DP_TCL_NUM_RING_MAX; i++) {
|
||||
spin_lock_bh(&ab->dp.tx_ring[i].tx_idr_lock);
|
||||
idr_for_each(&ab->dp.tx_ring[i].txbuf_idr,
|
||||
ath11k_mac_vif_unref, vif);
|
||||
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
|
||||
@@ -833,10 +833,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]);
|
||||
|
||||
+ len += scnprintf(buf + len, size - len, "\nTCL Ring idr 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.idr_na[i]);
|
||||
+
|
||||
+ len += scnprintf(buf + len, size - len, "\nMax Transmit Failures: %d\n",
|
||||
+ atomic_read(&soc_stats->tx_err.max_fail));
|
||||
+
|
||||
len += scnprintf(buf + len, size - len,
|
||||
"\nMisc Transmit Failures: %d\n",
|
||||
atomic_read(&soc_stats->tx_err.misc_fail));
|
||||
|
||||
+ len += scnprintf(buf + len, size - len,
|
||||
+ "\nNSS Transmit Failures: %d\n",
|
||||
+ atomic_read(&soc_stats->tx_err.nss_tx_fail));
|
||||
+
|
||||
len += ath11k_debugfs_dump_soc_ring_bp_stats(ab, buf + len, size - len);
|
||||
|
||||
if (len > size)
|
||||
--- a/drivers/net/wireless/ath/ath11k/core.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/core.c
|
||||
@@ -190,7 +190,6 @@ static struct ath11k_hw_params ath11k_hw
|
||||
.supports_regdb = false,
|
||||
.fix_l1ss = true,
|
||||
.credit_flow = false,
|
||||
- .max_tx_ring = DP_TCL_NUM_RING_MAX,
|
||||
.hal_params = &ath11k_hw_hal_params_ipq8074,
|
||||
.supports_dynamic_smps_6ghz = false,
|
||||
.alloc_cacheable_memory = true,
|
||||
@@ -216,6 +215,8 @@ static struct ath11k_hw_params ath11k_hw
|
||||
.smp2p_wow_exit = false,
|
||||
.support_fw_mac_sequence = false,
|
||||
.support_dual_stations = 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",
|
||||
@@ -362,7 +363,6 @@ static struct ath11k_hw_params ath11k_hw
|
||||
.supports_regdb = false,
|
||||
.fix_l1ss = true,
|
||||
.credit_flow = false,
|
||||
- .max_tx_ring = DP_TCL_NUM_RING_MAX,
|
||||
.hal_params = &ath11k_hw_hal_params_ipq8074,
|
||||
.supports_dynamic_smps_6ghz = true,
|
||||
.alloc_cacheable_memory = true,
|
||||
@@ -388,6 +388,8 @@ static struct ath11k_hw_params ath11k_hw
|
||||
.smp2p_wow_exit = false,
|
||||
.support_fw_mac_sequence = false,
|
||||
.support_dual_stations = false,
|
||||
+ /* 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",
|
||||
@@ -2320,6 +2322,9 @@ int ath11k_core_pre_init(struct ath11k_b
|
||||
if (nss_offload)
|
||||
ab->nss.stats_enabled = 1;
|
||||
|
||||
+ if (ab->nss.enabled && ab->hw_params.max_tx_ring > DP_TCL_NUM_RING_MAX)
|
||||
+ ab->hw_params.max_tx_ring = DP_TCL_NUM_RING_MAX;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_pre_init);
|
||||
--- a/drivers/net/wireless/ath/ath11k/hal_tx.h
|
||||
+++ b/drivers/net/wireless/ath/ath11k/hal_tx.h
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
struct hal_tx_info {
|
||||
u16 meta_data_flags; /* %HAL_TCL_DATA_CMD_INFO0_META_ */
|
||||
- u8 ring_id;
|
||||
+ u8 buf_id;
|
||||
u32 desc_id;
|
||||
enum hal_tcl_desc_type type;
|
||||
enum hal_tcl_encap_type encap_type;
|
||||
@@ -70,5 +70,5 @@ int ath11k_hal_reo_cmd_send(struct ath11
|
||||
enum hal_reo_cmd_type type,
|
||||
struct ath11k_hal_reo_cmd *cmd);
|
||||
void ath11k_hal_tx_init_data_ring(struct ath11k_base *ab,
|
||||
- struct hal_srng *srng);
|
||||
+ struct hal_srng *srng, enum hal_ring_type type);
|
||||
#endif
|
||||
--- a/drivers/net/wireless/ath/ath11k/hal_tx.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/hal_tx.c
|
||||
@@ -37,18 +37,18 @@ static const u8 dscp_tid_map[DSCP_TID_MA
|
||||
void ath11k_hal_tx_cmd_desc_setup(struct ath11k_base *ab, void *cmd,
|
||||
struct hal_tx_info *ti)
|
||||
{
|
||||
- struct hal_tcl_data_cmd *tcl_cmd = cmd;
|
||||
+ struct hal_tcl_data_cmd tcl_cmd, *tcl_desc = cmd;
|
||||
|
||||
- tcl_cmd->buf_addr_info.info0 =
|
||||
+ tcl_cmd.buf_addr_info.info0 =
|
||||
FIELD_PREP(BUFFER_ADDR_INFO0_ADDR, ti->paddr);
|
||||
- tcl_cmd->buf_addr_info.info1 =
|
||||
+ tcl_cmd.buf_addr_info.info1 =
|
||||
FIELD_PREP(BUFFER_ADDR_INFO1_ADDR,
|
||||
((uint64_t)ti->paddr >> HAL_ADDR_MSB_REG_SHIFT));
|
||||
- tcl_cmd->buf_addr_info.info1 |=
|
||||
- FIELD_PREP(BUFFER_ADDR_INFO1_RET_BUF_MGR, ti->rbm_id) |
|
||||
+ tcl_cmd.buf_addr_info.info1 |=
|
||||
+ FIELD_PREP(BUFFER_ADDR_INFO1_RET_BUF_MGR, ti->buf_id) |
|
||||
FIELD_PREP(BUFFER_ADDR_INFO1_SW_COOKIE, ti->desc_id);
|
||||
|
||||
- tcl_cmd->info0 =
|
||||
+ tcl_cmd.info0 =
|
||||
FIELD_PREP(HAL_TCL_DATA_CMD_INFO0_DESC_TYPE, ti->type) |
|
||||
FIELD_PREP(HAL_TCL_DATA_CMD_INFO0_ENCAP_TYPE, ti->encap_type) |
|
||||
FIELD_PREP(HAL_TCL_DATA_CMD_INFO0_ENCRYPT_TYPE,
|
||||
@@ -60,24 +60,26 @@ void ath11k_hal_tx_cmd_desc_setup(struct
|
||||
FIELD_PREP(HAL_TCL_DATA_CMD_INFO0_CMD_NUM,
|
||||
ti->meta_data_flags);
|
||||
|
||||
- tcl_cmd->info1 = ti->flags0 |
|
||||
+ tcl_cmd.info1 = ti->flags0 |
|
||||
FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_DATA_LEN, ti->data_len) |
|
||||
FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_PKT_OFFSET, ti->pkt_offset);
|
||||
|
||||
- tcl_cmd->info2 = ti->flags1 |
|
||||
+ tcl_cmd.info2 = ti->flags1 |
|
||||
FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_TID, ti->tid) |
|
||||
FIELD_PREP(HAL_TCL_DATA_CMD_INFO2_LMAC_ID, ti->lmac_id);
|
||||
|
||||
- tcl_cmd->info3 = FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_DSCP_TID_TABLE_IDX,
|
||||
+ tcl_cmd.info3 = FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_DSCP_TID_TABLE_IDX,
|
||||
ti->dscp_tid_tbl_idx) |
|
||||
FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_SEARCH_INDEX,
|
||||
ti->bss_ast_idx) |
|
||||
FIELD_PREP(HAL_TCL_DATA_CMD_INFO3_CACHE_SET_NUM,
|
||||
ti->bss_ast_hash);
|
||||
- tcl_cmd->info4 = 0;
|
||||
+ tcl_cmd.info4 = 0;
|
||||
|
||||
if (ti->enable_mesh)
|
||||
- ab->hw_params.hw_ops->tx_mesh_enable(ab, tcl_cmd);
|
||||
+ ab->hw_params.hw_ops->tx_mesh_enable(ab, &tcl_cmd);
|
||||
+
|
||||
+ *tcl_desc = tcl_cmd;
|
||||
}
|
||||
|
||||
void ath11k_hal_tx_set_dscp_tid_map(struct ath11k_base *ab, int id)
|
||||
@@ -137,7 +139,9 @@ void ath11k_hal_tx_set_dscp_tid_map(stru
|
||||
ctrl_reg_val);
|
||||
}
|
||||
|
||||
-void ath11k_hal_tx_init_data_ring(struct ath11k_base *ab, struct hal_srng *srng)
|
||||
+void ath11k_hal_tx_init_data_ring(struct ath11k_base *ab, struct hal_srng *srng,
|
||||
+ enum hal_ring_type type)
|
||||
+
|
||||
{
|
||||
struct hal_srng_params params;
|
||||
struct hal_tlv_hdr *tlv;
|
||||
@@ -146,7 +150,7 @@ void ath11k_hal_tx_init_data_ring(struct
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
|
||||
- entry_size = ath11k_hal_srng_get_entrysize(ab, HAL_TCL_DATA);
|
||||
+ entry_size = ath11k_hal_srng_get_entrysize(ab, type);
|
||||
ath11k_hal_srng_get_params(ab, srng, ¶ms);
|
||||
desc = (u8 *)params.ring_base_vaddr;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user