Skip to content

Commit e884a8a

Browse files
committed
firewire: core: call FCP address handlers outside RCU read-side critical section
The former commit added reference counting to ensure safe invocations of address handlers. Unlike the exclusive-region address handlers, all FCP address handlers should be called on receiving an FCP request. This commit uses the part of kernel stack to collect address handlers up to 4 within the section, then invoke them outside of the section. Reference counting ensures that each handler remains valid and safe to call. Lifting the limitation of supporting only 4 handlers is left for next work. Link: https://lore.kernel.org/r/20250803122015.236493-4-o-takashi@sakamocchi.jp Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
1 parent e8cf687 commit e884a8a

File tree

1 file changed

+19
-6
lines changed

1 file changed

+19
-6
lines changed

drivers/firewire/core-transaction.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -950,13 +950,17 @@ static void handle_exclusive_region_request(struct fw_card *card,
950950
put_address_handler(handler);
951951
}
952952

953+
// To use kmalloc allocator efficiently, this should be power of two.
954+
#define BUFFER_ON_KERNEL_STACK_SIZE 4
955+
953956
static void handle_fcp_region_request(struct fw_card *card,
954957
struct fw_packet *p,
955958
struct fw_request *request,
956959
unsigned long long offset)
957960
{
958-
struct fw_address_handler *handler;
959-
int tcode, destination, source;
961+
struct fw_address_handler *buffer_on_kernel_stack[BUFFER_ON_KERNEL_STACK_SIZE];
962+
struct fw_address_handler *handler, **handlers;
963+
int tcode, destination, source, i, count;
960964

961965
if ((offset != (CSR_REGISTER_BASE | CSR_FCP_COMMAND) &&
962966
offset != (CSR_REGISTER_BASE | CSR_FCP_RESPONSE)) ||
@@ -977,18 +981,27 @@ static void handle_fcp_region_request(struct fw_card *card,
977981
return;
978982
}
979983

984+
count = 0;
985+
handlers = buffer_on_kernel_stack;
980986
scoped_guard(rcu) {
981987
list_for_each_entry_rcu(handler, &address_handler_list, link) {
982988
if (is_enclosing_handler(handler, offset, request->length)) {
983989
get_address_handler(handler);
984-
handler->address_callback(card, request, tcode, destination, source,
985-
p->generation, offset, request->data,
986-
request->length, handler->callback_data);
987-
put_address_handler(handler);
990+
handlers[count] = handler;
991+
if (++count >= ARRAY_SIZE(buffer_on_kernel_stack))
992+
break;
988993
}
989994
}
990995
}
991996

997+
for (i = 0; i < count; ++i) {
998+
handler = handlers[i];
999+
handler->address_callback(card, request, tcode, destination, source,
1000+
p->generation, offset, request->data,
1001+
request->length, handler->callback_data);
1002+
put_address_handler(handler);
1003+
}
1004+
9921005
fw_send_response(card, request, RCODE_COMPLETE);
9931006
}
9941007

0 commit comments

Comments
 (0)