diff options
| author | Kiran K <kiran.k@intel.com> | 2026-07-15 21:47:53 +0530 |
|---|---|---|
| committer | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2026-08-07 12:36:01 -0400 |
| commit | e0650618ee8395cdefde1686e31d3ff5c253955e (patch) | |
| tree | 37d8db55443b866e9c2c11f134b41248d4bcbd3f /tools/perf/scripts/python/task-analyzer.py | |
| parent | e6b4232bde0219adb11334e65fe7577a21e86458 (diff) | |
Bluetooth: btintel_pcie: serialize reset_type with RECOVERY_IN_PROGRESS
The reset path had two concurrency holes. Both are reachable in
practice when btintel_pcie_hw_error() is invoked from the HCI rx
path while another reset is being requested or is already in
flight.
1. data->reset_type was a plain shared field. The hw_error path
wrote it BEFORE the test_and_set_bit(RECOVERY_IN_PROGRESS)
guard inside btintel_pcie_reset(), so a second hw_error could
clobber the type chosen by an earlier in-flight request:
CPU0 (reset_work) CPU1 (hw_error #2)
dev_data->reset_type = PLDR
T2: read reset_type
dev_data->reset_type = FLR
reset() test_and_set sees 1
-> drops, but type already
clobbered
The hdev->reset callback (.reset = btintel_pcie_reset,
invoked via the sysfs reset attribute
/sys/class/bluetooth/hciX/reset and from hci_cmd_timeout())
compounded this by not writing reset_type at all -- it
inherited whatever value a previous hw_error / resume() had
left, which could be PLDR.
2. btintel_pcie_dump_debug_registers() was called unconditionally
at the top of hw_error(). When reset_work was already running
pci_try_reset_function(), the BT MMIO window can read all-1s
or trigger AER for the duration of the FLR, polluting the
debug dump with no useful information.
Refactor the reset path to make RECOVERY_IN_PROGRESS the sole
serializer for both the type write and the work scheduling:
- Replace btintel_pcie_reset(hdev) with
btintel_pcie_request_reset(data, type). The helper takes the
desired reset variant as a parameter and writes
data->reset_type only after winning test_and_set_bit(); losers
return without touching the field, so concurrent triggers can
no longer clobber an in-flight reset's type. reset_work()'s
read of reset_type is now ordered after the bit transition via
schedule_work()'s memory barrier.
- Add a thin btintel_pcie_hci_reset() wrapper for the
hdev->reset callback (invoked via the sysfs reset attribute
/sys/class/bluetooth/hciX/reset and from hci_cmd_timeout())
that always requests FLR explicitly, so these paths no longer
inherit stale state from prior error events.
- Add an early test_bit(RECOVERY_IN_PROGRESS) gate at the top of
hw_error() so dump_debug_registers() and the recovery-counter
bookkeeping are skipped when a reset is already in flight; the
authoritative test_and_set lives in request_reset() and races
cleanly against any caller that passes the optimistic check.
- Convert the two resume() reset sites (FREEZE/HIBERNATE and the
D0-error path) to request_reset(data, FLR), removing the
redundant manual reset_type writes.
Assisted-by: GitHub-Copilot:claude-4.7-opus
Signed-off-by: Kiran K <kiran.k@intel.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Diffstat (limited to 'tools/perf/scripts/python/task-analyzer.py')
0 files changed, 0 insertions, 0 deletions
