diff options
| author | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2026-10-18 00:33:38 +0900 |
|---|---|---|
| committer | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2026-10-18 00:33:38 +0900 |
| commit | 491eaa94eae15cfe2d58c336c92566c8a1d6d74f (patch) | |
| tree | 12fea2223601382e5ed0b03e4c90d71faef53f3b | |
| parent | ba70002e180f8038201ac141b60ebb12fd8ca16d (diff) | |
| download | linux-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.c | 11 |
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 |
