diff options
Diffstat (limited to 'drivers/firewire/core-transaction.c')
| -rw-r--r-- | drivers/firewire/core-transaction.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 642387f0d7ca..7be4ae3b36b5 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -51,6 +51,34 @@ static void remove_transaction_entry(struct fw_card *card, struct fw_transaction card->transactions.tlabel_mask &= ~(1ULL << entry->tlabel); } +// Must be called without holding card->transactions.lock. +void fw_cancel_pending_transactions(struct fw_card *card) +{ + struct fw_transaction *t, *tmp; + LIST_HEAD(pending_list); + + // NOTE: This can be without irqsave when we can guarantee that __fw_send_request() for + // local destination never runs in any type of IRQ context. + 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); + + if (!t->with_tstamp) { + t->callback.without_tstamp(card, RCODE_CANCELLED, NULL, 0, + t->callback_data); + } else { + t->callback.with_tstamp(card, RCODE_CANCELLED, t->packet.timestamp, 0, + NULL, 0, t->callback_data); + } + } +} + // card->transactions.lock must be acquired in advance. #define find_and_pop_transaction_entry(card, condition) \ ({ \ |
