Inter-revision diff: patch 7

Comparing v1 (message) to v2 (message)

--- v1
+++ v2
@@ -1,53 +1,74 @@
-No completion interrupts will occur while an endpoint is suspended,
-or when a channel has been stopped for suspend.  So there's no need
-to disable the interrupt during suspend and re-enable it when
-resuming.
+Transactions to send data for a network device can be allocated at
+any time up until the point the TX queue is stopped.  It is possible
+for ipa_start_xmit() to be called in one context just before a
+the transmit queue is stopped in another.
 
-We'll enable the interrupt when we first start the channel, and
-disable it again only when it's "really" stopped.
+Update gsi_channel_trans_last() so that for TX channels the
+allocated and pending transaction lists are checked--in addition
+to the completed and polled lists--to determine the "last"
+transaction.  This means any transaction that has been allocated
+before the TX queue is stopped will be allowed to complete before
+we conclude the channel is quiesced.
+
+Rework the function a bit to use a list pointer and gotos.
 
 Signed-off-by: Alex Elder <elder@linaro.org>
 ---
- drivers/net/ipa/gsi.c | 18 ++----------------
- 1 file changed, 2 insertions(+), 16 deletions(-)
+ drivers/net/ipa/gsi.c | 34 +++++++++++++++++++++++++---------
+ 1 file changed, 25 insertions(+), 9 deletions(-)
 
 diff --git a/drivers/net/ipa/gsi.c b/drivers/net/ipa/gsi.c
-index 70647e8450845..74d1dd04ad6e9 100644
+index 03498182ad024..8b64cbe4737a4 100644
 --- a/drivers/net/ipa/gsi.c
 +++ b/drivers/net/ipa/gsi.c
-@@ -959,30 +959,16 @@ void gsi_channel_reset(struct gsi *gsi, u32 channel_id, bool doorbell)
- int gsi_channel_suspend(struct gsi *gsi, u32 channel_id, bool stop)
- {
- 	struct gsi_channel *channel = &gsi->channel[channel_id];
--	int ret;
- 
--	/* No completions when suspended; disable interrupt if successful */
--	ret = __gsi_channel_stop(channel, stop);
--	if (!ret)
--		gsi_irq_ieob_disable_one(gsi, channel->evt_ring_id);
--
--	return ret;
-+	return __gsi_channel_stop(channel, stop);
+@@ -725,22 +725,38 @@ static void gsi_evt_ring_program(struct gsi *gsi, u32 evt_ring_id)
+ 	gsi_evt_ring_doorbell(gsi, evt_ring_id, 0);
  }
  
- /* Resume a suspended channel (starting will be requested if STOPPED) */
- int gsi_channel_resume(struct gsi *gsi, u32 channel_id, bool start)
+-/* Return the last (most recent) transaction completed on a channel. */
++/* Find the transaction whose completion indicates a channel is quiesced */
+ static struct gsi_trans *gsi_channel_trans_last(struct gsi_channel *channel)
  {
- 	struct gsi_channel *channel = &gsi->channel[channel_id];
--	int ret;
+ 	struct gsi_trans_info *trans_info = &channel->trans_info;
++	const struct list_head *list;
+ 	struct gsi_trans *trans;
  
--	/* Re-enable the completion interrupt */
--	gsi_irq_ieob_enable_one(gsi, channel->evt_ring_id);
--
--	ret = __gsi_channel_start(channel, start);
--	if (ret)
--		gsi_irq_ieob_disable_one(gsi, channel->evt_ring_id);
--
--	return ret;
-+	return __gsi_channel_start(channel, start);
- }
+ 	spin_lock_bh(&trans_info->spinlock);
  
- /**
+-	if (!list_empty(&trans_info->complete))
+-		trans = list_last_entry(&trans_info->complete,
+-					struct gsi_trans, links);
+-	else if (!list_empty(&trans_info->polled))
+-		trans = list_last_entry(&trans_info->polled,
+-					struct gsi_trans, links);
+-	else
+-		trans = NULL;
++	/* There is a small chance a TX transaction got allocated just
++	 * before we disabled transmits, so check for that.
++	 */
++	if (channel->toward_ipa) {
++		list = &trans_info->alloc;
++		if (!list_empty(list))
++			goto done;
++		list = &trans_info->pending;
++		if (!list_empty(list))
++			goto done;
++	}
++
++	/* Otherwise (TX or RX) we want to wait for anything that
++	 * has completed, or has been polled but not released yet.
++	 */
++	list = &trans_info->complete;
++	if (!list_empty(list))
++		goto done;
++	list = &trans_info->polled;
++	if (list_empty(list))
++		list = NULL;
++done:
++	trans = list ? list_last_entry(list, struct gsi_trans, links) : NULL;
+ 
+ 	/* Caller will wait for this, so take a reference */
+ 	if (trans)
 -- 
 2.27.0
 
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help