[PATCH net-next 3/6] net: ipa: use IDs exclusively for last transaction
From: Alex Elder <hidden>
Date: 2022-09-02 21:02:43
Also in:
linux-arm-msm, lkml
Subsystem:
networking drivers, qcom ipa driver, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Alex Elder, Linus Torvalds
Always use transaction IDs when finding the "last" transaction to await when quiescing a channel. This basically extends what was done in the previous patch to all other transaction state IDs. As a result we are no longer updating any transaction lists inside gsi_channel_trans_last(), so there's no need to take the spinlock. Signed-off-by: Alex Elder <redacted> --- drivers/net/ipa/gsi.c | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ipa/gsi.c b/drivers/net/ipa/gsi.c
index 135e51980d793..0983a11409f2d 100644
--- a/drivers/net/ipa/gsi.c
+++ b/drivers/net/ipa/gsi.c@@ -714,8 +714,6 @@ static struct gsi_trans *gsi_channel_trans_last(struct gsi_channel *channel) u16 trans_index; u16 trans_id; - spin_lock_bh(&trans_info->spinlock); - /* There is a small chance a TX transaction got allocated just * before we disabled transmits, so check for that. */
@@ -728,32 +726,46 @@ static struct gsi_trans *gsi_channel_trans_last(struct gsi_channel *channel) goto done; } - trans = list_last_entry_or_null(&trans_info->committed, - struct gsi_trans, links); - if (trans) + /* Last committed transaction precedes the first allocated */ + if (trans_info->committed_id != trans_info->allocated_id) { + trans_id = trans_info->allocated_id - 1; + trans_index = trans_id % channel->tre_count; + trans = &trans_info->trans[trans_index]; goto done; - trans = list_last_entry_or_null(&trans_info->pending, - struct gsi_trans, links); - if (trans) + } + + /* Last pending transaction precedes the first committed */ + if (trans_info->pending_id != trans_info->committed_id) { + trans_id = trans_info->committed_id - 1; + trans_index = trans_id % channel->tre_count; + trans = &trans_info->trans[trans_index]; goto done; + } } /* Otherwise (TX or RX) we want to wait for anything that * has completed, or has been polled but not released yet. + * + * The last pending transaction precedes the first committed. */ - trans = list_last_entry_or_null(&trans_info->complete, - struct gsi_trans, links); - if (trans) + if (trans_info->completed_id != trans_info->pending_id) { + trans_id = trans_info->pending_id - 1; + trans_index = trans_id % channel->tre_count; + trans = &trans_info->trans[trans_index]; goto done; - trans = list_last_entry_or_null(&trans_info->polled, - struct gsi_trans, links); + } + if (trans_info->polled_id != trans_info->completed_id) { + trans_id = trans_info->completed_id - 1; + trans_index = trans_id % channel->tre_count; + trans = &trans_info->trans[trans_index]; + } else { + trans = NULL; + } done: /* Caller will wait for this, so take a reference */ if (trans) refcount_inc(&trans->refcount); - spin_unlock_bh(&trans_info->spinlock); - return trans; }
--
2.34.1