-
-
Notifications
You must be signed in to change notification settings - Fork 877
Add module to patch ath12k firmware #1711
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
TwoUnderscorez
wants to merge
2
commits into
NixOS:master
Choose a base branch
from
TwoUnderscorez:patch-ath12k-fw
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # Linux Firmware | ||
|
|
||
| Module for patching files in the Linux firmware. | ||
|
|
||
| See [ath12k](ath12k/README.md) for an example when this might be needed. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| # linux-firmware/ath12k | ||
|
|
||
| ## The problem | ||
|
|
||
| The [Linux Firmware](https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/ath12k) already contains the [ath12k firmware](https://git.codelinaro.org/clo/ath-firmware/ath12k-firmware) which contains various `board-2.bin`files which are containers of the actual firmware files. The kernel module tries to load a firmware file from within the `board-2.bin` container based on the device ID that the WiFi card reports. As itt turns out, there are WiFi cards with device IDs that aren't included in any of the firmware files in the `board-2.bin` container. | ||
|
|
||
| See the following bug reports on the [Kernel's Bugzilla](https://bugzilla.kernel.org/): | ||
| 1. [Bug 217971](https://bugzilla.kernel.org/show_bug.cgi?id=217971) | ||
| 1. [Bug 219319](https://bugzilla.kernel.org/show_bug.cgi?id=219319) | ||
| 1. [Bug 218741](https://bugzilla.kernel.org/show_bug.cgi?id=218741) | ||
| 1. [Bug 219239](https://bugzilla.kernel.org/show_bug.cgi?id=219239) | ||
| 1. [Bug 220897](https://bugzilla.kernel.org/show_bug.cgi?id=220897) | ||
|
|
||
| ## The solution | ||
|
|
||
| The solution is pointed out in some of the issues mentioned above - patch the `board-2.bin` with the device ID that your WiFi card reports. To do that, unpack the `board-2.bin` with [`bdecoder`](https://raw.githubusercontent.com/qca/qca-swiss-army-knife/99ecb87c5f808e98096eeddd5d804eeb0cf51d18/tools/scripts/ath12k/ath12k-bdencoder), edit the JSON and repack it. Then install the firmware as you normally would according to the [official readme](https://git.codelinaro.org/clo/ath-firmware/ath12k-firmware/-/blob/main/README.md?ref_type=heads). | ||
|
|
||
| The only problem is that it's not clear to which firmware file you should add the device ID of your WiFi card. Unfortunately, my best answer is keep trying until you find one that works. | ||
|
|
||
| ## The Nix Solution | ||
|
|
||
| 1. Import this module. | ||
| 2. Run `sudo dmesg|grep -i ath12k`, you should see a line to the effect of: | ||
| ``` | ||
| [ 15.743621] ath12k_pci 0000:07:00.0: failed to fetch board data for X from ath12k/Y | ||
| ``` | ||
| 3. Place this in your NixOS Configuration: | ||
| ```nix | ||
| linux-firmware-ath12k-patched = { | ||
| enable = true; | ||
| fw-name = "X"; | ||
| fw-board2 = "Y"; | ||
| }; | ||
| ``` | ||
| 4. Build your NixOS Configuration, you should see an error to the effect of: | ||
| ``` | ||
| ┏━ 4 Errors: | ||
| ⋮ | ||
| ┃ > "bus=pci,vendor=17cb,device=1107,subsystem-vendor=17aa,subsystem-device=e0e6,qmi-chip-id=2,qmi-board-id=255,variant=LE.bin", | ||
| ┃ > "bus=pci,vendor=17cb,device=1107,subsystem-vendor=17aa,subsystem-device=e0e6,qmi-chip-id=2,qmi-board-id=255,variant=LE_Eiger.bin", | ||
| ┃ > "bus=pci,vendor=17cb,device=1107,subsystem-vendor=105b,subsystem-device=e0ea,qmi-chip-id=2,qmi-board-id=255,variant=AC_RAY16ZPB.bin", | ||
| ┃ > "bus=pci,vendor=17cb,device=1107,subsystem-vendor=105b,subsystem-device=e10d,qmi-chip-id=2,qmi-board-id=255.bin" | ||
| ┃ > ] | ||
| ┃ > ================================================================================ | ||
| ┃ > Fatal error: please choose one of the values above and set them as the fw-file | ||
| ┃ > Traceback (most recent call last): | ||
| ┃ > File "<stdin>", line 18, in <module> | ||
| ┃ > RuntimeError: Fatal error: please choose one of the values above and set them as the fw-file | ||
| ┃ For full logs, run: | ||
| ┃ nix log /nix/store/gha0dc3ziaz16pfv321iyzchr380m4v9-linux-firmware-ath12k-patched-0-unstable-2025-12-05.drv | ||
| ┣━ Dependency Graph: | ||
| ┃ ┌─ ⏸ linux-zen-6.18.1-modules-shrunk waiting for 1 ⏵ | ||
| ┃ ┌─ ⏸ initrd-linux-zen-6.18.1 | ||
| ┃ ┌─ ⏸ boot.json | ||
| ┃ │ ┌─ ⏵ linux-firmware-ath12k-patched-0-unstable-2025-12-05 (buildPhase) | ||
| ┃ │ ┌─ ⏸ linux-firmware-ath12k-patched-0-unstable-2025-12-05-zstd | ||
| ┃ │ ┌─ ⏸ firmware | ||
| ┃ │ ┌─ ⏸ etc-modprobe.d-firmware.conf | ||
| ┃ │ ├─ ⏵ system-units | ||
| ┃ ├─ ⏸ etc | ||
| ┃ ⏸ nixos-system-ron-desktop-25.11.20251225.5900a0a | ||
| ┣━━━ Builds | ||
| ┗━ ∑ ⏵ 2 │ ✔ 1 │ ⏸ 8 │ ⚠ Exited with 4 errors reported by nix at 22:43:30 after 7s | ||
| Error: | ||
| 0: Failed to build configuration | ||
| 1: Command exited with status Exited(1) | ||
|
|
||
| Location: | ||
| src/commands.rs:693 | ||
| ``` | ||
| 5. Run the command printed below the line that says "For full logs, run:" to view the full log. Scroll up to see the list of firmware files that this module can assign your device ID to. You can either scroll up further to look at the original JSON and try to find a similar device ID to what you have and use that, or copy the list of possible values to a file and try each one until one of them work. | ||
| 6. Assuming you chose a firmware file in the previous step (a string that ends with '.bin'), add the following line to your configuration and apply it: | ||
| ```nix | ||
| linux-firmware-ath12k-patched = { | ||
| /* enable, fw-name, fw-board2 as before */ | ||
| fw-file = "some-very-long-file-name.bin"; | ||
| }; | ||
| ``` | ||
| 7. Reboot and examine `sudo dmesg|grep -i ath12k`. If there are no errors, try to scan and connect to a WiFi network. Make sure you can see all the networks you expect to see (e.g. 2.4Ghz, 5 Ghz and 6Ghz). If anything fails, go back to step 5. | ||
|
|
||
| If you've tried all the firmware files and some things don't work properly, as far as I know, I'm afraid you're out of luck. For example, I got 2.4Ghz and 5Ghz (6Ghz untested) to work, but Bluetooth isn't working. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| { | ||
| pkgs, | ||
| lib, | ||
| config, | ||
| ... | ||
| }: | ||
| { | ||
| options = { | ||
| linux-firmware-ath12k-patched = { | ||
| enable = lib.mkEnableOption "enables linux-firmware-ath12k-patched"; | ||
| fw-name = lib.mkOption { | ||
| type = lib.types.str; | ||
| description = '' | ||
| The device name of your WiFi card. That is, if your dmesg says | ||
| "failed to fetch board data for X from ath12k/Y" then this is X | ||
| ''; | ||
| example = ''bus=pci,vendor=17cb,device=1107,subsystem-vendor=1eac,subsystem-device=8001,qmi-chip-id=2,qmi-board-id=255''; | ||
| }; | ||
| fw-board2 = lib.mkOption { | ||
| type = lib.types.str; | ||
| description = '' | ||
| The path to the board-2.bin you'd like to patch RELATIVE TO the | ||
| ath12k folder. That is, if your dmesg says | ||
| "failed to fetch board data for X from ath12k/Y" then this is Y. | ||
| ''; | ||
| example = ''WCN7850/hw2.0/board-2.bin''; | ||
| }; | ||
| fw-file = lib.mkOption { | ||
| type = lib.types.str; | ||
| default = ""; | ||
| description = '' | ||
| This is the firmware file you'd like to use. To see a list of | ||
| available files leave this setting blank, which will cause the | ||
| build to fail and the list of files to be printed to the build log.. | ||
| ''; | ||
| example = ''bus=pci,vendor=17cb,device=1107,subsystem-vendor=17aa,subsystem-device=e0e6,qmi-chip-id=2,qmi-board-id=255.bin''; | ||
| }; | ||
| }; | ||
| }; | ||
|
|
||
| config = lib.mkIf config.linux-firmware-ath12k-patched.enable { | ||
| hardware.firmware = | ||
| with pkgs; | ||
| with config.linux-firmware-ath12k-patched; | ||
| [ | ||
| (stdenvNoCC.mkDerivation rec { | ||
| pname = "linux-firmware-ath12k-patched"; | ||
| version = "0-unstable-2025-12-05"; | ||
|
|
||
| src = fetchgit { | ||
| url = "https://git.codelinaro.org/clo/ath-firmware/ath12k-firmware.git"; | ||
| hash = "sha256-DIoj91XELnFj4xludxJCZRHctS4fYQ2khiFWrPdKHoo="; | ||
| rev = "8253b9185d292ba1ad27654f74b7a3abc68fca9c"; | ||
| }; | ||
|
|
||
| bdecoder = fetchurl { | ||
| url = "https://raw.githubusercontent.com/qca/qca-swiss-army-knife/99ecb87c5f808e98096eeddd5d804eeb0cf51d18/tools/scripts/ath12k/ath12k-bdencoder"; | ||
| hash = "sha256-/cyNyWKNZ+UA1Jah3iLoLhNt3q7DJmnqGzrdk/KYBlI="; | ||
| }; | ||
|
|
||
| fw-repo = fetchurl { | ||
| url = "https://raw.githubusercontent.com/qca/qca-swiss-army-knife/99ecb87c5f808e98096eeddd5d804eeb0cf51d18/tools/scripts/ath12k/ath12k-fw-repo"; | ||
| hash = "sha256-7NvmddwqLiVeB+A2moll1YFH1/0j8rTtgDXGtmJ6hIA="; | ||
| }; | ||
|
|
||
| nativeBuildInputs = [ | ||
| python3 | ||
| ]; | ||
|
|
||
| buildPhase = '' | ||
| mkdir board-2 && cd $_ | ||
| export RES_DIR=$PWD | ||
| python3 $bdecoder --extract $src/${fw-board2} | ||
| python3 << EOF | ||
| import json | ||
| with open('board-2.json', 'r') as f: | ||
| board2 = json.load(f) | ||
| data = '${fw-file}' | ||
| name = '${fw-name}' | ||
| if not data: | ||
| print("="*80) | ||
| print('=== Dumping JSON for ${fw-board2}') | ||
| print("="*80) | ||
| print(json.dumps(board2, indent=4)) | ||
| print("="*80) | ||
| print('=== Dumping list of available options for fw-file') | ||
| print("="*80) | ||
| print(json.dumps([d['data'] for d in board2[0]['board']], indent=4)) | ||
| print("="*80) | ||
| error_string = 'Fatal error: please choose one of the values above and set them as the fw-file' | ||
| print(error_string) | ||
| raise RuntimeError(error_string) | ||
| for b in board2[0]['board']: | ||
| if b['data'] == data: | ||
| b['names'].append(name) | ||
| with open('board-2.json', 'w') as f: | ||
| json.dump(board2, f) | ||
| EOF | ||
| python3 $bdecoder -c ./board-2.json -o patched-board-2.bin | ||
| ''; | ||
|
|
||
| installPhase = '' | ||
| runHook preInstall | ||
|
|
||
| cd $src | ||
| mkdir -p $out//lib/firmware | ||
| python3 ${fw-repo} --install $out//lib/firmware | ||
| cp $RES_DIR/patched-board-2.bin $out/lib/firmware/ath12k/${fw-board2} | ||
|
|
||
| runHook postInstall | ||
| ''; | ||
| }) | ||
| ]; | ||
| }; | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you you know any laptop module where this apply? I mainly want to get some basic evaluation coverage for this code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a good example?
I don't know of any laptop that comes with a wifi chip with unsupported device ids as I have a desktop. I did try to plug the module into a few laptops of mine in case it was my desktop motherboard's fault, but all my computers ended up not recognizing this chip exactly the same.
Because the code merely adds the device id you define to the json and doesn't override anything, you could test it on a computer with Qualcomm wifi chip that already works and make sure that it still works when using this module.
Sorry, this is indeed a very quirky module for very quirky hardware, let me know if there is anything else I can do.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it's time to find an alternative to parsing our README.md table to figure out what needs to be evaluated and instead use flake outputs to import each module into its own nixos configuration. Than your module would be tested automatically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I didn't know that the readme was being parsed automatically.
Is there anything you want me to do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Mic92 Do you think this can be merged or is there anything you'd like me to change?