Skip to content

Conversation

@WhatAmISupposedToPutHere

No description provided.

marcan and others added 30 commits November 20, 2023 11:25
People keep complaining about this and think their wifi is broken for
some reason...

Signed-off-by: Hector Martin <marcan@marcan.st>
This is the counterpart to b50255c. In MSI mode we can still get MSIs
even with IRQs disabled, so add an explicit gate for it.

Signed-off-by: Hector Martin <marcan@marcan.st>
SYSMEM corerev 12+ uses different coreinfo masks for the ROM/RAM sizes.
The masks for cores <12 also look like they were wrong all along, since
the register layout is not the same as for SOCRAM (even though it was
sharing the defines). Plus we need to skip the ROM banks, which we
weren't doing.

So it looks like this was always wrong for SYSMEM chips. Fix it and add
support for the new revisions.

Signed-off-by: Hector Martin <marcan@marcan.st>
Beginning with BCM4388, Apple machines are using firmware signing. This
requires a new firmware blob (as the signature is provided out-of-band)
as well as an extension of the existing random seed upload mechanism to
populate the data structures required for signature verification by the
bootloader.

To implement this, refactor the existing random seed code to be more
generic, and use it to implement the signature upload.

Drive-by changes: Remove two unused members of brcmf_pciedev_info (which
are confusing as they are never initialized), and also zero out the
unused portion of TCM to make TCM dumps less noisy. With this, the TCM
contents are 1:1 identical to what the macOS driver ends up doing,
except for the NVRAM which has the injected macaddr property at the end
instead of at the start.

Signed-off-by: Hector Martin <marcan@marcan.st>
New chips, bigger rings again. BCM4388 Apple firmware posts more than
1024 RX buffers, so we need to bump this up again.

This also requires increasing the number of RX PKTIDs.

Signed-off-by: Hector Martin <marcan@marcan.st>
BCM4388 supports more bands, so make space for them.

Signed-off-by: Hector Martin <marcan@marcan.st>
…y number

This is the ca7 version of 3c7c07c ("wifi: brcmfmac: chip: Only disable
D11 cores; handle an arbitrary number"). Instead of the hack in
resetcore to handle multiple 80211 cores, let's just iterate in
set_passive.

Signed-off-by: Hector Martin <marcan@marcan.st>
On newer cores, we need to explicitly set the subsystems to reset via
the watchdog. Logic adapted from bcmdhd.

Signed-off-by: Hector Martin <marcan@marcan.st>
Currently the pcie code multiplexes all register accesses through a
single window. This isn't very efficient, and it creates race conditions
when we access registers from multiple paths (e.g. in the interrupt
handler). Since the chip has a dedicated window for the PCIe core
registers, we can use that instead, avoid all the gratuitous window
switching, and fix the IRQ race issues.

Signed-off-by: Hector Martin <marcan@marcan.st>
Newer firmwares notify the host of boot completion via an MSI, so let's
make sure that is initialized before booting the firmware.

Signed-off-by: Hector Martin <marcan@marcan.st>
With secure boot, the vector is not accessible and trying to write it
triggers PCIe errors. Skip it in that case.

Signed-off-by: Hector Martin <marcan@marcan.st>
Make sure the firmware can't get any early notifications by masking all
IRQs explicitly before loading the firmware.

Signed-off-by: Hector Martin <marcan@marcan.st>
This is essentially identical to SCAN_V2 with an extra field where we
had a padding byte, so don't bother duplicating the entire structure.
Just add the field and the logic to set the version properly.

Signed-off-by: Hector Martin <marcan@marcan.st>
This extended command supports bit set/clear operations, but we just use
it like the old full mask set command.

Signed-off-by: Hector Martin <marcan@marcan.st>
The structures are compatible and just add fields, so we can just treat
it as always v112. If we start using new fields, that will have to be
gated on the version.

Signed-off-by: Hector Martin <marcan@marcan.st>
New firmware wants extra fields, hopefully old firmware ignores them.

Signed-off-by: Hector Martin <marcan@marcan.st>
Signed-off-by: Hector Martin <marcan@marcan.st>
Fix access point mode by bringing firmware into appropriate state before setting up the device.

Signed-off-by: Patrick Blass <patrickblass.dev@gmail.com>
This patch fixes the firmware memory map structure to be complete.
Along the way, we fix a failure to align the heap memory start address,
which causes failures with the newest apple wifi firmware.

With this patch, we can load the latest (sonoma 14.0 as of right now) apple wifi firmware.

Signed-off-by: Daniel Berlin <dberlin@dberlin.org>
This patch adds support for 6G chanspecs, as part of adding 6G and
802.11ax support.

Signed-off-by: Daniel Berlin <dberlin@dberlin.org>
1. Correct VHT MCS settings to support as many tx/rx streams as chip
   does.

2. Correct VHT capabilities to support what all chips do.

3. Correct max AMPDU capabilities for VHT.

4. Support LDPC and STBC in VHT where available.

Signed-off-by: Daniel Berlin <dberlin@dberlin.org>
…tructure.

Signed-off-by: Daniel Berlin <dberlin@dberlin.org>
This patch adds support for using GCMP/etc during offload
where supported by the firmware.

Signed-off-by: Daniel Berlin <dberlin@dberlin.org>
We may just have had to clone a packet, and not actually
have run out of headroom.  Only issue warning about headroom
when we actually ran out of headroom.
This removes useless spam about needing 0 more bytes of headroom.

Signed-off-by: Daniel Berlin <dberlin@dberlin.org>
This patch adds support for handling the scan flags that come from the
802.11 stack.  This enables the stack to control whether we are doing
high/low power scans, as well as other options.

Signed-off-by: Daniel Berlin <dberlin@dberlin.org>
This patch adds support for 6G bands, along with HE capabilities,
as they are required to register 6G bands with wiphy.
This in turn, enables 802.11ax support for the other bands.

Scanning is not updated in this patch, so the bands are unused
except to be able to process what the firmware tells us.

Existing code is updated to handle all the bands rather than just 2g and
5g channels.

Signed-off-by: Daniel Berlin <dberlin@dberlin.org>
Currently, we ignore the default country in the reg notifier.
We also register a custom regulatory domain, which is set
as the default.
As a result, the chip is likely to be set to the correct country,
but the regulatory domain will not match it.

When the regulatory notifier is then called, we see the countries
are the same and do not change anything, even though the domain
is wrong.

This patch forces us to reset the bands on the first country change
even if the chip is already set to that country.

We also restore the original band info before reconstructing channel
info, as the new regdom power limits may be higher than what is
currently set.

Signed-off-by: Daniel Berlin <dberlin@dberlin.org>
Signed-off-by: Daniel Berlin <dberlin@dberlin.org>
Signed-off-by: Daniel Berlin <dberlin@dberlin.org>
This patch structurizes PNF scan handling, adding support for
netinfo v3 and PNO v3 structures.

This in turn, enables the chip to tell us about 6G scan results,
as the results contain chanspecs and not just channels.

Signed-off-by: Daniel Berlin <dberlin@dberlin.org>
marcan and others added 22 commits December 17, 2023 14:35
Signed-off-by: Sasha Finkelstein <fnkl.kernel@gmail.com>
@jannau
Copy link
Member

jannau commented Mar 5, 2024

@jannau
Copy link
Member

jannau commented Apr 29, 2024

merged in asahi-wip / asahi-6.8.8-1

@jannau jannau closed this Apr 29, 2024
WhatAmISupposedToPutHere pushed a commit to WhatAmISupposedToPutHere/linux that referenced this pull request Mar 4, 2025
Since commit 6037802 ("power: supply: core: implement extension API")
there is the following ABBA deadlock (simplified) between the LED trigger
code and the power-supply code:

1) When registering a power-supply class device, power_supply_register()
calls led_trigger_register() from power_supply_create_triggers() in
a scoped_guard(rwsem_read, &psy->extensions_sem) context.
led_trigger_register() then in turn takes a LED subsystem lock.
So here we have the following locking order:

* Read-lock extensions_sem
* Lock LED subsystem lock(s)

2) When registering a LED class device, with its default trigger set
to a power-supply LED trigger (which has already been registered)
The LED class code calls power_supply_led_trigger_activate() when
setting up the default trigger. power_supply_led_trigger_activate()
calls power_supply_get_property() to determine the initial value of
to assign to the LED and that read-locks extensions_sem. So now we
have the following locking order:

* Lock LED subsystem lock(s)
* Read-lock extensions_sem

Fixing this is easy, there is no need to hold the extensions_sem when
calling power_supply_create_triggers() since all triggers are always
created rather then checking for the presence of certain attributes as
power_supply_add_hwmon_sysfs() does. Move power_supply_create_triggers()
out of the guard block to fix this.

Here is the lockdep report fixed by this change:

[   31.249343] ======================================================
[   31.249378] WARNING: possible circular locking dependency detected
[   31.249413] 6.13.0-rc6+ AsahiLinux#251 Tainted: G         C  E
[   31.249440] ------------------------------------------------------
[   31.249471] (udev-worker)/553 is trying to acquire lock:
[   31.249501] ffff892adbcaf660 (&psy->extensions_sem){.+.+}-{4:4}, at: power_supply_get_property.part.0+0x22/0x150
[   31.249574]
               but task is already holding lock:
[   31.249603] ffff892adbc0bad0 (&led_cdev->trigger_lock){+.+.}-{4:4}, at: led_trigger_set_default+0x34/0xe0
[   31.249657]
               which lock already depends on the new lock.

[   31.249696]
               the existing dependency chain (in reverse order) is:
[   31.249735]
               -> #2 (&led_cdev->trigger_lock){+.+.}-{4:4}:
[   31.249778]        down_write+0x3b/0xd0
[   31.249803]        led_trigger_set_default+0x34/0xe0
[   31.249833]        led_classdev_register_ext+0x311/0x3a0
[   31.249863]        input_leds_connect+0x1dc/0x2a0
[   31.249889]        input_attach_handler.isra.0+0x75/0x90
[   31.249921]        input_register_device.cold+0xa1/0x150
[   31.249955]        hidinput_connect+0x8a2/0xb80
[   31.249982]        hid_connect+0x582/0x5c0
[   31.250007]        hid_hw_start+0x3f/0x60
[   31.250030]        hid_device_probe+0x122/0x1f0
[   31.250053]        really_probe+0xde/0x340
[   31.250080]        __driver_probe_device+0x78/0x110
[   31.250105]        driver_probe_device+0x1f/0xa0
[   31.250132]        __device_attach_driver+0x85/0x110
[   31.250160]        bus_for_each_drv+0x78/0xc0
[   31.250184]        __device_attach+0xb0/0x1b0
[   31.250207]        bus_probe_device+0x94/0xb0
[   31.250230]        device_add+0x64a/0x860
[   31.250252]        hid_add_device+0xe5/0x240
[   31.250279]        usbhid_probe+0x4dc/0x620
[   31.250303]        usb_probe_interface+0xe4/0x2a0
[   31.250329]        really_probe+0xde/0x340
[   31.250353]        __driver_probe_device+0x78/0x110
[   31.250377]        driver_probe_device+0x1f/0xa0
[   31.250404]        __device_attach_driver+0x85/0x110
[   31.250431]        bus_for_each_drv+0x78/0xc0
[   31.250455]        __device_attach+0xb0/0x1b0
[   31.250478]        bus_probe_device+0x94/0xb0
[   31.250501]        device_add+0x64a/0x860
[   31.250523]        usb_set_configuration+0x606/0x8a0
[   31.250552]        usb_generic_driver_probe+0x3e/0x60
[   31.250579]        usb_probe_device+0x3d/0x120
[   31.250605]        really_probe+0xde/0x340
[   31.250629]        __driver_probe_device+0x78/0x110
[   31.250653]        driver_probe_device+0x1f/0xa0
[   31.250680]        __device_attach_driver+0x85/0x110
[   31.250707]        bus_for_each_drv+0x78/0xc0
[   31.250731]        __device_attach+0xb0/0x1b0
[   31.250753]        bus_probe_device+0x94/0xb0
[   31.250776]        device_add+0x64a/0x860
[   31.250798]        usb_new_device.cold+0x141/0x38f
[   31.250828]        hub_event+0x1166/0x1980
[   31.250854]        process_one_work+0x20f/0x580
[   31.250879]        worker_thread+0x1d1/0x3b0
[   31.250904]        kthread+0xee/0x120
[   31.250926]        ret_from_fork+0x30/0x50
[   31.250954]        ret_from_fork_asm+0x1a/0x30
[   31.250982]
               -> #1 (triggers_list_lock){++++}-{4:4}:
[   31.251022]        down_write+0x3b/0xd0
[   31.251045]        led_trigger_register+0x40/0x1b0
[   31.251074]        power_supply_register_led_trigger+0x88/0x150
[   31.251107]        power_supply_create_triggers+0x55/0xe0
[   31.251135]        __power_supply_register.part.0+0x34e/0x4a0
[   31.251164]        devm_power_supply_register+0x70/0xc0
[   31.251190]        bq27xxx_battery_setup+0x1a1/0x6d0 [bq27xxx_battery]
[   31.251235]        bq27xxx_battery_i2c_probe+0xe5/0x17f [bq27xxx_battery_i2c]
[   31.251272]        i2c_device_probe+0x125/0x2b0
[   31.251299]        really_probe+0xde/0x340
[   31.251324]        __driver_probe_device+0x78/0x110
[   31.251348]        driver_probe_device+0x1f/0xa0
[   31.251375]        __driver_attach+0xba/0x1c0
[   31.251398]        bus_for_each_dev+0x6b/0xb0
[   31.251421]        bus_add_driver+0x111/0x1f0
[   31.251445]        driver_register+0x6e/0xc0
[   31.251470]        i2c_register_driver+0x41/0xb0
[   31.251498]        do_one_initcall+0x5e/0x3a0
[   31.251522]        do_init_module+0x60/0x220
[   31.251550]        __do_sys_init_module+0x15f/0x190
[   31.251575]        do_syscall_64+0x93/0x180
[   31.251598]        entry_SYSCALL_64_after_hwframe+0x76/0x7e
[   31.251629]
               -> #0 (&psy->extensions_sem){.+.+}-{4:4}:
[   31.251668]        __lock_acquire+0x13ce/0x21c0
[   31.251694]        lock_acquire+0xcf/0x2e0
[   31.251719]        down_read+0x3e/0x170
[   31.251741]        power_supply_get_property.part.0+0x22/0x150
[   31.251774]        power_supply_update_leds+0x8d/0x230
[   31.251804]        power_supply_led_trigger_activate+0x18/0x20
[   31.251837]        led_trigger_set+0x1fc/0x300
[   31.251863]        led_trigger_set_default+0x90/0xe0
[   31.251892]        led_classdev_register_ext+0x311/0x3a0
[   31.251921]        devm_led_classdev_multicolor_register_ext+0x6e/0xb80 [led_class_multicolor]
[   31.251969]        ktd202x_probe+0x464/0x5c0 [leds_ktd202x]
[   31.252002]        i2c_device_probe+0x125/0x2b0
[   31.252027]        really_probe+0xde/0x340
[   31.252052]        __driver_probe_device+0x78/0x110
[   31.252076]        driver_probe_device+0x1f/0xa0
[   31.252103]        __driver_attach+0xba/0x1c0
[   31.252125]        bus_for_each_dev+0x6b/0xb0
[   31.252148]        bus_add_driver+0x111/0x1f0
[   31.252172]        driver_register+0x6e/0xc0
[   31.252197]        i2c_register_driver+0x41/0xb0
[   31.252225]        do_one_initcall+0x5e/0x3a0
[   31.252248]        do_init_module+0x60/0x220
[   31.252274]        __do_sys_init_module+0x15f/0x190
[   31.253986]        do_syscall_64+0x93/0x180
[   31.255826]        entry_SYSCALL_64_after_hwframe+0x76/0x7e
[   31.257614]
               other info that might help us debug this:

[   31.257619] Chain exists of:
                 &psy->extensions_sem --> triggers_list_lock --> &led_cdev->trigger_lock

[   31.257630]  Possible unsafe locking scenario:

[   31.257632]        CPU0                    CPU1
[   31.257633]        ----                    ----
[   31.257634]   lock(&led_cdev->trigger_lock);
[   31.257637]                                lock(triggers_list_lock);
[   31.257640]                                lock(&led_cdev->trigger_lock);
[   31.257643]   rlock(&psy->extensions_sem);
[   31.257646]
                *** DEADLOCK ***

[   31.289433] 4 locks held by (udev-worker)/553:
[   31.289443]  #0: ffff892ad9658108 (&dev->mutex){....}-{4:4}, at: __driver_attach+0xaf/0x1c0
[   31.289463]  #1: ffff892adbc0bbc8 (&led_cdev->led_access){+.+.}-{4:4}, at: led_classdev_register_ext+0x1c7/0x3a0
[   31.289476]  #2: ffffffffad0e30b0 (triggers_list_lock){++++}-{4:4}, at: led_trigger_set_default+0x2c/0xe0
[   31.289487]  #3: ffff892adbc0bad0 (&led_cdev->trigger_lock){+.+.}-{4:4}, at: led_trigger_set_default+0x34/0xe0

Fixes: 6037802 ("power: supply: core: implement extension API")
Cc: Thomas Weißschuh <linux@weissschuh.net>
Cc: Armin Wolf <W_Armin@gmx.de>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Thomas Weißschuh <linux@weissschuh.net>
Link: https://lore.kernel.org/r/20250130140035.20636-1-hdegoede@redhat.com
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
jannau pushed a commit that referenced this pull request Oct 12, 2025
commit 3e31a6b upstream.

There is a bug observed when rtw89_core_tx_kick_off_and_wait() tries to
access already freed skb_data:

 BUG: KFENCE: use-after-free write in rtw89_core_tx_kick_off_and_wait drivers/net/wireless/realtek/rtw89/core.c:1110

 CPU: 6 UID: 0 PID: 41377 Comm: kworker/u64:24 Not tainted  6.17.0-rc1+ #1 PREEMPT(lazy)
 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS edk2-20250523-14.fc42 05/23/2025
 Workqueue: events_unbound cfg80211_wiphy_work [cfg80211]

 Use-after-free write at 0x0000000020309d9d (in kfence-#251):
 rtw89_core_tx_kick_off_and_wait drivers/net/wireless/realtek/rtw89/core.c:1110
 rtw89_core_scan_complete drivers/net/wireless/realtek/rtw89/core.c:5338
 rtw89_hw_scan_complete_cb drivers/net/wireless/realtek/rtw89/fw.c:7979
 rtw89_chanctx_proceed_cb drivers/net/wireless/realtek/rtw89/chan.c:3165
 rtw89_chanctx_proceed drivers/net/wireless/realtek/rtw89/chan.h:141
 rtw89_hw_scan_complete drivers/net/wireless/realtek/rtw89/fw.c:8012
 rtw89_mac_c2h_scanofld_rsp drivers/net/wireless/realtek/rtw89/mac.c:5059
 rtw89_fw_c2h_work drivers/net/wireless/realtek/rtw89/fw.c:6758
 process_one_work kernel/workqueue.c:3241
 worker_thread kernel/workqueue.c:3400
 kthread kernel/kthread.c:463
 ret_from_fork arch/x86/kernel/process.c:154
 ret_from_fork_asm arch/x86/entry/entry_64.S:258

 kfence-#251: 0x0000000056e2393d-0x000000009943cb62, size=232, cache=skbuff_head_cache

 allocated by task 41377 on cpu 6 at 77869.159548s (0.009551s ago):
 __alloc_skb net/core/skbuff.c:659
 __netdev_alloc_skb net/core/skbuff.c:734
 ieee80211_nullfunc_get net/mac80211/tx.c:5844
 rtw89_core_send_nullfunc drivers/net/wireless/realtek/rtw89/core.c:3431
 rtw89_core_scan_complete drivers/net/wireless/realtek/rtw89/core.c:5338
 rtw89_hw_scan_complete_cb drivers/net/wireless/realtek/rtw89/fw.c:7979
 rtw89_chanctx_proceed_cb drivers/net/wireless/realtek/rtw89/chan.c:3165
 rtw89_chanctx_proceed drivers/net/wireless/realtek/rtw89/chan.c:3194
 rtw89_hw_scan_complete drivers/net/wireless/realtek/rtw89/fw.c:8012
 rtw89_mac_c2h_scanofld_rsp drivers/net/wireless/realtek/rtw89/mac.c:5059
 rtw89_fw_c2h_work drivers/net/wireless/realtek/rtw89/fw.c:6758
 process_one_work kernel/workqueue.c:3241
 worker_thread kernel/workqueue.c:3400
 kthread kernel/kthread.c:463
 ret_from_fork arch/x86/kernel/process.c:154
 ret_from_fork_asm arch/x86/entry/entry_64.S:258

 freed by task 1045 on cpu 9 at 77869.168393s (0.001557s ago):
 ieee80211_tx_status_skb net/mac80211/status.c:1117
 rtw89_pci_release_txwd_skb drivers/net/wireless/realtek/rtw89/pci.c:564
 rtw89_pci_release_tx_skbs.isra.0 drivers/net/wireless/realtek/rtw89/pci.c:651
 rtw89_pci_release_tx drivers/net/wireless/realtek/rtw89/pci.c:676
 rtw89_pci_napi_poll drivers/net/wireless/realtek/rtw89/pci.c:4238
 __napi_poll net/core/dev.c:7495
 net_rx_action net/core/dev.c:7557 net/core/dev.c:7684
 handle_softirqs kernel/softirq.c:580
 do_softirq.part.0 kernel/softirq.c:480
 __local_bh_enable_ip kernel/softirq.c:407
 rtw89_pci_interrupt_threadfn drivers/net/wireless/realtek/rtw89/pci.c:927
 irq_thread_fn kernel/irq/manage.c:1133
 irq_thread kernel/irq/manage.c:1257
 kthread kernel/kthread.c:463
 ret_from_fork arch/x86/kernel/process.c:154
 ret_from_fork_asm arch/x86/entry/entry_64.S:258

It is a consequence of a race between the waiting and the signaling side
of the completion:

            Waiting thread                            Completing thread

rtw89_core_tx_kick_off_and_wait()
  rcu_assign_pointer(skb_data->wait, wait)
  /* start waiting */
  wait_for_completion_timeout()
                                                rtw89_pci_tx_status()
                                                  rtw89_core_tx_wait_complete()
                                                    rcu_read_lock()
                                                    /* signals completion and
                                                     * proceeds further
                                                     */
                                                    complete(&wait->completion)
                                                    rcu_read_unlock()
                                                  ...
                                                  /* frees skb_data */
                                                  ieee80211_tx_status_ni()
  /* returns (exit status doesn't matter) */
  wait_for_completion_timeout()
  ...
  /* accesses the already freed skb_data */
  rcu_assign_pointer(skb_data->wait, NULL)

The completing side might proceed and free the underlying skb even before
the waiting side is fully awoken and run to execution.  Actually the race
happens regardless of wait_for_completion_timeout() exit status, e.g.
the waiting side may hit a timeout and the concurrent completing side is
still able to free the skb.

Skbs which are sent by rtw89_core_tx_kick_off_and_wait() are owned by the
driver.  They don't come from core ieee80211 stack so no need to pass them
to ieee80211_tx_status_ni() on completing side.

Introduce a work function which will act as a garbage collector for
rtw89_tx_wait_info objects and the associated skbs.  Thus no potentially
heavy locks are required on the completing side.

Found by Linux Verification Center (linuxtesting.org).

Fixes: 1ae5ca6 ("wifi: rtw89: add function to wait for completion of TX skbs")
Cc: stable@vger.kernel.org
Suggested-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru>
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20250919210852.823912-2-pchelkin@ispras.ru
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants