diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 83c29a487d86..a43fc3a278f2 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -811,7 +811,9 @@ void fw_core_remove_card(struct fw_card *card) drain_workqueue(card->isoc_wq); drain_workqueue(card->async_wq); card->driver->disable(card); - fw_cancel_pending_transactions(card); + + scoped_guard(spinlock_irqsave, &card->transactions.lock) + fw_cancel_pending_transactions(card); scoped_guard(spinlock_irqsave, &card->lock) fw_destroy_nodes(card); diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 08536275be12..8e4951631185 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -69,28 +69,6 @@ static void invoke_callback(struct fw_transaction *t, int rcode, u32 response_ts } } -// Must be called without holding card->transactions.lock. -void fw_cancel_pending_transactions(struct fw_card *card) -__must_not_hold(&card->transactions.lock) -{ - struct fw_transaction *t, *tmp; - LIST_HEAD(pending_list); - - lockdep_assert_not_held(&card->transactions.lock); - - scoped_guard(spinlock_irqsave, &card->transactions.lock) { - list_for_each_entry_safe(t, tmp, &card->transactions.list, link) { - if (try_cancel_split_timeout(t)) - list_move(&t->link, &pending_list); - } - } - - list_for_each_entry_safe(t, tmp, &pending_list, link) { - list_del(&t->link); - invoke_callback(t, RCODE_CANCELLED, 0, NULL, 0); - } -} - // card->transactions.lock must be acquired in advance. #define find_and_pop_transaction_entry(card, condition) \ ({ \ @@ -118,6 +96,21 @@ static void schedule_error_callback(struct fw_transaction *t, int rcode, u32 res queue_work(t->card->async_wq, &t->error_work); } +void fw_cancel_pending_transactions(struct fw_card *card) +__must_hold(&card->transactions.lock) +{ + struct fw_transaction *t, *tmp; + + lockdep_assert_held(&card->transactions.lock); + + list_for_each_entry_safe(t, tmp, &card->transactions.list, link) { + if (try_cancel_split_timeout(t)) { + remove_transaction_entry(card, t); + schedule_error_callback(t, RCODE_CANCELLED, 0); + } + } +} + /** * fw_cancel_transaction: cancel transaction. * @card: interface where the transaction has been requested