summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2026-10-18 00:33:38 +0900
committerTakashi Sakamoto <o-takashi@sakamocchi.jp>2026-10-18 00:33:38 +0900
commit491eaa94eae15cfe2d58c336c92566c8a1d6d74f (patch)
tree12fea2223601382e5ed0b03e4c90d71faef53f3b
parentba70002e180f8038201ac141b60ebb12fd8ca16d (diff)
downloadlinux-next-491eaa94eae15cfe2d58c336c92566c8a1d6d74f.tar.gz
linux-next-491eaa94eae15cfe2d58c336c92566c8a1d6d74f.zip
firewire: core: don't disable error work for transaction
The error callback work is scheduled only when the transaction instance is no longer on the pending list. Therefore, iterating over the list to cancel the work is pointless. Remove the code that cancels the work while iterating over the pending list. Once scheduled, the work can run and invoke the error callback without being cancelled. Link: https://lore.kernel.org/r/20261017153339.267337-2-o-takashi@sakamocchi.jp Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
-rw-r--r--drivers/firewire/core-transaction.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c
index 589dd25b9785..3f7c4ec4d618 100644
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -44,7 +44,7 @@ static int try_cancel_split_timeout(struct fw_transaction *t)
lockdep_assert_held(&t->card->transactions.lock);
if (t->is_split_transaction)
- return timer_delete(&t->split_timeout_timer) || disable_work(&t->error_work);
+ return timer_delete(&t->split_timeout_timer);
else
return 1;
}
@@ -150,16 +150,22 @@ __must_not_hold(&card->transactions.lock)
transaction->response_timestamp = cycle_time_to_ohci_tstamp(curr_cycle_time);
transaction->rcode = RCODE_CANCELLED;
- enable_and_queue_work(card->async_wq, &transaction->error_work);
+ queue_work(card->async_wq, &transaction->error_work);
return 0;
}
EXPORT_SYMBOL(fw_cancel_transaction);
+// Ensure that the transaction is not on the pending list when scheduling this work. Cancelling
+// the work after scheduling makes no sense, as the initiator must be notified of the transaction
+// result.
static void error_callback_work(struct work_struct *work)
{
struct fw_transaction *t = from_work(t, work, error_work);
+ // To detect programming mistakes.
+ WARN_ON(!list_empty(&t->link));
+
invoke_callback(t, t->rcode, t->response_timestamp, NULL, 0);
}
@@ -418,6 +424,7 @@ __must_not_hold(&card->transactions.lock)
t->with_tstamp = with_tstamp;
t->callback_data = callback_data;
INIT_WORK(&t->error_work, error_callback_work);
+ INIT_LIST_HEAD(&t->link);
/*
* Allocate tlabel from the bitmap and put the transaction on