From 8540ec31c831419c79ad65be2f515a9d8bbde257 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 11 Oct 2026 15:31:44 +0900 Subject: [PATCH] firewire: core: use context analysis annotations and lockdep checks for split timeout lock The spinlock protects parameters related to split transaction timeouts. Add context analysis annotations and lockdep checks for this lock. Link: https://lore.kernel.org/r/20261009121048.282982-5-o-takashi@sakamocchi.jp Link: https://lore.kernel.org/r/20261011063146.497455-5-o-takashi@sakamocchi.jp Signed-off-by: Takashi Sakamoto --- drivers/firewire/core-transaction.c | 31 ++++++++++++++++++----------- include/linux/firewire.h | 8 ++++---- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 6b461142e30f..4d60f4998c6e 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -210,11 +210,13 @@ static u32 compute_split_timeout_timestamp(struct fw_card *card, u32 request_tim static void transmit_complete_callback(struct fw_packet *packet, struct fw_card *card, int status) +__must_not_hold(&card->split_timeout.lock) __must_not_hold(&card->transactions.lock) { struct fw_transaction *t = container_of(packet, struct fw_transaction, packet); + lockdep_assert_not_held(&card->split_timeout.lock); lockdep_assert_not_held(&card->transactions.lock); trace_async_request_outbound_complete((uintptr_t)t, card->index, packet->generation, @@ -898,11 +900,14 @@ __must_hold(&card->split_timeout.lock) static struct fw_request *allocate_request(struct fw_card *card, struct fw_packet *p) +__must_not_hold(&card->split_timeout.lock) { struct fw_request *request; u32 *data, length; int request_tcode; + lockdep_assert_not_held(&card->split_timeout.lock); + request_tcode = async_header_get_tcode(p->header); switch (request_tcode) { case TCODE_WRITE_QUADLET_REQUEST: @@ -1320,6 +1325,8 @@ __must_hold(&card->split_timeout.lock) { unsigned int cycles; + lockdep_assert_held(&card->split_timeout.lock); + cycles = card->split_timeout.hi * 8000 + (card->split_timeout.lo >> 19); /* minimum per IEEE 1394, maximum which doesn't overflow OHCI */ @@ -1375,28 +1382,28 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, break; case CSR_SPLIT_TIMEOUT_HI: - if (tcode == TCODE_READ_QUADLET_REQUEST) { - *data = cpu_to_be32(card->split_timeout.hi); - } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) { - scoped_guard(spinlock, &card->split_timeout.lock) { + scoped_guard(spinlock, &card->split_timeout.lock) { + if (tcode == TCODE_READ_QUADLET_REQUEST) { + *data = cpu_to_be32(card->split_timeout.hi); + } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) { card->split_timeout.hi = be32_to_cpu(*data) & 7; update_split_timeout(card); + } else { + rcode = RCODE_TYPE_ERROR; } - } else { - rcode = RCODE_TYPE_ERROR; } break; case CSR_SPLIT_TIMEOUT_LO: - if (tcode == TCODE_READ_QUADLET_REQUEST) { - *data = cpu_to_be32(card->split_timeout.lo); - } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) { - scoped_guard(spinlock, &card->split_timeout.lock) { + scoped_guard(spinlock, &card->split_timeout.lock) { + if (tcode == TCODE_READ_QUADLET_REQUEST) { + *data = cpu_to_be32(card->split_timeout.lo); + } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) { card->split_timeout.lo = be32_to_cpu(*data) & 0xfff80000; update_split_timeout(card); + } else { + rcode = RCODE_TYPE_ERROR; } - } else { - rcode = RCODE_TYPE_ERROR; } break; diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 89db958dea2e..a3660ad1a1d4 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -99,10 +99,10 @@ struct fw_card { } transactions; struct { - u32 hi; - u32 lo; - unsigned int cycles; - unsigned int jiffies; + u32 hi __guarded_by(&lock); + u32 lo __guarded_by(&lock); + unsigned int cycles __guarded_by(&lock); + unsigned int jiffies __guarded_by(&lock); spinlock_t lock; } split_timeout;