Skip to content

Commit 036176d

Browse files
committed
firewire: core: abort pending transactions at card removal
IEEE 1394 defines the split, concatenated, and unified transaction. To support the split transaction, core function uses linked list to maintain the transactions waiting for acknowledge packet. After clearing sources of hardware interrupts, the acknowledge packet is no longer handled, therefore it is required to abort the pending transactions. This commit executes callback with RCODE_CANCELLED for the pending transactions at card removal. Link: https://lore.kernel.org/r/20251111223834.311287-1-o-takashi@sakamocchi.jp Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
1 parent ae1ef2f commit 036176d

4 files changed

Lines changed: 31 additions & 5 deletions

File tree

drivers/firewire/core-card.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,7 @@ void fw_core_remove_card(struct fw_card *card)
790790
drain_workqueue(card->isoc_wq);
791791
drain_workqueue(card->async_wq);
792792
card->driver->disable(card);
793+
fw_cancel_pending_transactions(card);
793794

794795
scoped_guard(spinlock_irqsave, &card->lock)
795796
fw_destroy_nodes(card);

drivers/firewire/core-transaction.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,34 @@ static void remove_transaction_entry(struct fw_card *card, struct fw_transaction
5151
card->transactions.tlabel_mask &= ~(1ULL << entry->tlabel);
5252
}
5353

54+
// Must be called without holding card->transactions.lock.
55+
void fw_cancel_pending_transactions(struct fw_card *card)
56+
{
57+
struct fw_transaction *t, *tmp;
58+
LIST_HEAD(pending_list);
59+
60+
// NOTE: This can be without irqsave when we can guarantee that __fw_send_request() for
61+
// local destination never runs in any type of IRQ context.
62+
scoped_guard(spinlock_irqsave, &card->transactions.lock) {
63+
list_for_each_entry_safe(t, tmp, &card->transactions.list, link) {
64+
if (try_cancel_split_timeout(t))
65+
list_move(&t->link, &pending_list);
66+
}
67+
}
68+
69+
list_for_each_entry_safe(t, tmp, &pending_list, link) {
70+
list_del(&t->link);
71+
72+
if (!t->with_tstamp) {
73+
t->callback.without_tstamp(card, RCODE_CANCELLED, NULL, 0,
74+
t->callback_data);
75+
} else {
76+
t->callback.with_tstamp(card, RCODE_CANCELLED, t->packet.timestamp, 0,
77+
NULL, 0, t->callback_data);
78+
}
79+
}
80+
}
81+
5482
// card->transactions.lock must be acquired in advance.
5583
#define find_and_pop_transaction_entry(card, condition) \
5684
({ \

drivers/firewire/core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,8 @@ void fw_fill_response(struct fw_packet *response, u32 *request_header,
287287
void fw_request_get(struct fw_request *request);
288288
void fw_request_put(struct fw_request *request);
289289

290+
void fw_cancel_pending_transactions(struct fw_card *card);
291+
290292
// Convert the value of IEEE 1394 CYCLE_TIME register to the format of timeStamp field in
291293
// descriptors of 1394 OHCI.
292294
static inline u32 cycle_time_to_ohci_tstamp(u32 tstamp)

drivers/firewire/ohci.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3719,11 +3719,6 @@ static void pci_remove(struct pci_dev *dev)
37193719

37203720
fw_core_remove_card(&ohci->card);
37213721

3722-
/*
3723-
* FIXME: Fail all pending packets here, now that the upper
3724-
* layers can't queue any more.
3725-
*/
3726-
37273722
software_reset(ohci);
37283723

37293724
irq = pci_irq_vector(dev, 0);

0 commit comments

Comments
 (0)