[PATCH v3 4/6] firewire: core: use context analysis annotations and lockdep checks for split timeout lock
From: Takashi Sakamoto
Date: Sun Oct 11 2026 - 02:32:57 EST
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@xxxxxxxxxxxxx
Signed-off-by: Takashi Sakamoto <o-takashi@xxxxxxxxxxxxx>
---
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 4466499dc1c9..bd6d28f9bc50 100644
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -206,6 +206,7 @@ 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)
{
lockdep_assert_not_held(&card->transactions.lock);
@@ -213,6 +214,7 @@ __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,
@@ -896,11 +898,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:
@@ -1318,6 +1323,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 */
@@ -1373,28 +1380,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;
--
2.53.0