Commit d320bac9 authored by Takashi Sakamoto's avatar Takashi Sakamoto
Browse files

firewire: core: use guard macro to maintain list of asynchronous transaction

The core function maintains pending asynchronous transactions by list in
the instance of fw_card. The concurrent access to the list is protected
by spinlock in the instance.

This commit uses guard macro to maintain the spinlock.

Link: https://lore.kernel.org/r/20240805085408.251763-14-o-takashi@sakamocchi.jp


Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
parent b9545448
Loading
Loading
Loading
Loading
+34 −51
Original line number Diff line number Diff line
@@ -49,35 +49,31 @@ static int close_transaction(struct fw_transaction *transaction, struct fw_card
			     u32 response_tstamp)
{
	struct fw_transaction *t = NULL, *iter;
	unsigned long flags;

	spin_lock_irqsave(&card->lock, flags);
	scoped_guard(spinlock_irqsave, &card->lock) {
		list_for_each_entry(iter, &card->transaction_list, link) {
			if (iter == transaction) {
			if (!try_cancel_split_timeout(iter)) {
				spin_unlock_irqrestore(&card->lock, flags);
				goto timed_out;
			}
				if (try_cancel_split_timeout(iter)) {
					list_del_init(&iter->link);
					card->tlabel_mask &= ~(1ULL << iter->tlabel);
					t = iter;
				}
				break;
			}
		}
	spin_unlock_irqrestore(&card->lock, flags);
	}

	if (!t)
		return -ENOENT;

	if (t) {
	if (!t->with_tstamp) {
		t->callback.without_tstamp(card, rcode, NULL, 0, t->callback_data);
	} else {
			t->callback.with_tstamp(card, rcode, t->packet.timestamp, response_tstamp,
						NULL, 0, t->callback_data);
		}
		return 0;
		t->callback.with_tstamp(card, rcode, t->packet.timestamp, response_tstamp, NULL, 0,
					t->callback_data);
	}

 timed_out:
	return -ENOENT;
	return 0;
}

/*
@@ -121,16 +117,13 @@ static void split_transaction_timeout_callback(struct timer_list *timer)
{
	struct fw_transaction *t = from_timer(t, timer, split_timeout_timer);
	struct fw_card *card = t->card;
	unsigned long flags;

	spin_lock_irqsave(&card->lock, flags);
	if (list_empty(&t->link)) {
		spin_unlock_irqrestore(&card->lock, flags);
	scoped_guard(spinlock_irqsave, &card->lock) {
		if (list_empty(&t->link))
			return;
	}
		list_del(&t->link);
		card->tlabel_mask &= ~(1ULL << t->tlabel);
	spin_unlock_irqrestore(&card->lock, flags);
	}

	if (!t->with_tstamp) {
		t->callback.without_tstamp(card, RCODE_CANCELLED, NULL, 0, t->callback_data);
@@ -143,20 +136,14 @@ static void split_transaction_timeout_callback(struct timer_list *timer)
static void start_split_transaction_timeout(struct fw_transaction *t,
					    struct fw_card *card)
{
	unsigned long flags;

	spin_lock_irqsave(&card->lock, flags);
	guard(spinlock_irqsave)(&card->lock);

	if (list_empty(&t->link) || WARN_ON(t->is_split_transaction)) {
		spin_unlock_irqrestore(&card->lock, flags);
	if (list_empty(&t->link) || WARN_ON(t->is_split_transaction))
		return;
	}

	t->is_split_transaction = true;
	mod_timer(&t->split_timeout_timer,
		  jiffies + card->split_timeout_jiffies);

	spin_unlock_irqrestore(&card->lock, flags);
}

static u32 compute_split_timeout_timestamp(struct fw_card *card, u32 request_timestamp);
@@ -1015,7 +1002,6 @@ EXPORT_SYMBOL(fw_core_handle_request);
void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
{
	struct fw_transaction *t = NULL, *iter;
	unsigned long flags;
	u32 *data;
	size_t data_length;
	int tcode, tlabel, source, rcode;
@@ -1054,26 +1040,23 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
		break;
	}

	spin_lock_irqsave(&card->lock, flags);
	scoped_guard(spinlock_irqsave, &card->lock) {
		list_for_each_entry(iter, &card->transaction_list, link) {
			if (iter->node_id == source && iter->tlabel == tlabel) {
			if (!try_cancel_split_timeout(iter)) {
				spin_unlock_irqrestore(&card->lock, flags);
				goto timed_out;
			}
				if (try_cancel_split_timeout(iter)) {
					list_del_init(&iter->link);
					card->tlabel_mask &= ~(1ULL << iter->tlabel);
					t = iter;
				}
				break;
			}
		}
	spin_unlock_irqrestore(&card->lock, flags);
	}

	trace_async_response_inbound((uintptr_t)t, card->index, p->generation, p->speed, p->ack,
				     p->timestamp, p->header, data, data_length / 4);

	if (!t) {
 timed_out:
		fw_notice(card, "unsolicited response (source %x, tlabel %x)\n",
			  source, tlabel);
		return;