[PATCH 5/5] firewire: ohci: refactor handling of local AT request/response packets

From: Takashi Sakamoto

Date: Sun Sep 13 2026 - 06:14:32 EST


For an asynchronous transaction to one of the two CSR address ranges on
the local node, the current implementation generates the packet data for
the response subaction internally while handling the request subaction.
Unlike transactions to other addresses, there is no need to submit the new
packet for the response subaction.

The current implementation handles both subactions in a single helper
function with conditional statements. This makes it difficult to see why
the two subactions should be handled differently.

Split the helper function into two helper functions, one for the request
subaction and the other for the response subaction.

Signed-off-by: Takashi Sakamoto <o-takashi@xxxxxxxxxxxxx>
---
drivers/firewire/ohci.c | 39 +++++++++++++++++++++++----------------
1 file changed, 23 insertions(+), 16 deletions(-)

diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 8a0aedf50a92..bd3e01b2f450 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -1536,14 +1536,11 @@ static bool in_bus_management_csr_registers(u64 offset)
return in_range(offset, CSR_BUS_MANAGER_ID, 0x22c - CSR_BUS_MANAGER_ID);
}

-static void handle_local_request(struct at_context *ctx, struct fw_packet *packet)
+static void handle_local_at_request_packet(struct fw_ohci *ohci, struct fw_packet *packet)
{
- struct fw_ohci *ohci = ctx->context.ohci;
-
- if (ctx == &ohci->at_request_ctx) {
- packet->ack = ACK_PENDING;
- packet->callback(packet, &ohci->card, packet->ack);
- }
+ // Emulate split transaction.
+ packet->ack = ACK_PENDING;
+ packet->callback(packet, &ohci->card, packet->ack);

u64 csr_offset = async_header_get_offset(packet->header) - CSR_REGISTER_BASE;

@@ -1563,16 +1560,23 @@ static void handle_local_request(struct at_context *ctx, struct fw_packet *packe
// Finish the transaction immediately.
fw_core_handle_response(&ohci->card, &response);
} else {
- if (ctx == &ohci->at_request_ctx)
- fw_core_handle_request(&ohci->card, packet);
- else
- fw_core_handle_response(&ohci->card, packet);
+ fw_core_handle_request(&ohci->card, packet);
}
+}

- if (ctx == &ohci->at_response_ctx) {
- packet->ack = ACK_COMPLETE;
- packet->callback(packet, &ohci->card, packet->ack);
- }
+static void handle_local_at_response_packet(struct fw_ohci *ohci, struct fw_packet *packet)
+{
+ u64 csr_offset = async_header_get_offset(packet->header) - CSR_REGISTER_BASE;
+
+ // The transaction is already finished by handle_local_at_request_packet().
+ if (WARN_ON(in_config_rom_csr_registers(csr_offset)) ||
+ WARN_ON(in_bus_management_csr_registers(csr_offset)))
+ return;
+
+ fw_core_handle_response(&ohci->card, packet);
+
+ packet->ack = ACK_COMPLETE;
+ packet->callback(packet, &ohci->card, packet->ack);
}

static bool destination_is_local(const struct fw_packet *packet, const struct fw_ohci *ohci)
@@ -1598,7 +1602,10 @@ static void at_context_transmit(struct at_context *ctx, struct fw_packet *packet
// Timestamping on behalf of the hardware.
packet->timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ohci));

- handle_local_request(ctx, packet);
+ if (ctx == &ohci->at_request_ctx)
+ handle_local_at_request_packet(ohci, packet);
+ else
+ handle_local_at_response_packet(ohci, packet);
return;
}

--
2.53.0