Commit 821c7733 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'net-ipa-more-multi-channel-event-ring-work'

Alex Elder says:

====================
net: ipa: more multi-channel event ring work

This series makes a little more progress toward supporting multiple
channels with a single event ring.  The first removes the assumption
that consecutive events are associated with the same RX channel.

The second derives the channel associated with an event from the
event itself, and the next does a small cleanup enabled by that.

The fourth causes updates to occur for every event processed (rather
once).  And the final patch does a little more rework to make TX
completion have more in common with RX completion.
====================

Link: https://lore.kernel.org/r/20220615165929.5924-1-elder@linaro.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 6c0d09d9 81765eea
......@@ -1344,14 +1344,19 @@ gsi_event_trans(struct gsi *gsi, struct gsi_event *event)
}
/**
* gsi_evt_ring_rx_update() - Record lengths of received data
* @evt_ring: Event ring associated with channel that received packets
* @index: Event index in ring reported by hardware
* gsi_evt_ring_update() - Update transaction state from hardware
* @gsi: GSI pointer
* @evt_ring_id: Event ring ID
* @index: Event index in ring reported by hardware
*
* Events for RX channels contain the actual number of bytes received into
* the buffer. Every event has a transaction associated with it, and here
* we update transactions to record their actual received lengths.
*
* When an event for a TX channel arrives we use information in the
* transaction to report the number of requests and bytes have been
* transferred.
*
* This function is called whenever we learn that the GSI hardware has filled
* new events since the last time we checked. The ring's index field tells
* the first entry in need of processing. The index provided is the
......@@ -1362,29 +1367,24 @@ gsi_event_trans(struct gsi *gsi, struct gsi_event *event)
*
* Note that @index always refers to an element *within* the event ring.
*/
static void gsi_evt_ring_rx_update(struct gsi_evt_ring *evt_ring, u32 index)
static void gsi_evt_ring_update(struct gsi *gsi, u32 evt_ring_id, u32 index)
{
struct gsi_channel *channel = evt_ring->channel;
struct gsi_evt_ring *evt_ring = &gsi->evt_ring[evt_ring_id];
struct gsi_ring *ring = &evt_ring->ring;
struct gsi_trans_info *trans_info;
struct gsi_event *event_done;
struct gsi_event *event;
struct gsi_trans *trans;
u32 event_avail;
u32 old_index;
trans_info = &channel->trans_info;
/* We'll start with the oldest un-processed event. RX channels
* replenish receive buffers in single-TRE transactions, so we
* can just map that event to its transaction. Transactions
* associated with completion events are consecutive.
/* Starting with the oldest un-processed event, determine which
* transaction (and which channel) is associated with the event.
* For RX channels, update each completed transaction with the
* number of bytes that were actually received. For TX channels
* associated with a network device, report to the network stack
* the number of transfers and bytes this completion represents.
*/
old_index = ring->index;
event = gsi_ring_virt(ring, old_index);
trans = gsi_event_trans(channel->gsi, event);
if (!trans)
return;
/* Compute the number of events to process before we wrap,
* and determine when we'll be done processing events.
......@@ -1392,15 +1392,28 @@ static void gsi_evt_ring_rx_update(struct gsi_evt_ring *evt_ring, u32 index)
event_avail = ring->count - old_index % ring->count;
event_done = gsi_ring_virt(ring, index);
do {
trans->len = __le16_to_cpu(event->len);
struct gsi_trans *trans;
trans = gsi_event_trans(gsi, event);
if (!trans)
return;
if (trans->direction == DMA_FROM_DEVICE)
trans->len = __le16_to_cpu(event->len);
else
gsi_trans_tx_completed(trans);
gsi_trans_move_complete(trans);
/* Move on to the next event and transaction */
if (--event_avail)
event++;
else
event = gsi_ring_virt(ring, 0);
trans = gsi_trans_pool_next(&trans_info->pool, trans);
} while (event != event_done);
/* Tell the hardware we've handled these events */
gsi_evt_ring_doorbell(gsi, evt_ring_id, index);
}
/* Initialize a ring, including allocating DMA memory for its entries */
......@@ -1499,15 +1512,7 @@ static struct gsi_trans *gsi_channel_update(struct gsi_channel *channel)
* the number of transactions and bytes this completion represents
* up the network stack.
*/
if (channel->toward_ipa)
gsi_trans_tx_completed(trans);
else
gsi_evt_ring_rx_update(evt_ring, index);
gsi_trans_move_complete(trans);
/* Tell the hardware we've handled these events */
gsi_evt_ring_doorbell(gsi, evt_ring_id, index);
gsi_evt_ring_update(gsi, evt_ring_id, index);
return gsi_channel_trans_complete(channel);
}
......
......@@ -16,9 +16,6 @@ struct gsi_channel;
#define GSI_RING_ELEMENT_SIZE 16 /* bytes; must be a power of 2 */
/* Return the entry that follows one provided in a transaction pool */
void *gsi_trans_pool_next(struct gsi_trans_pool *pool, void *element);
/**
* gsi_trans_move_complete() - Mark a GSI transaction completed
* @trans: Transaction to commit
......
......@@ -214,26 +214,14 @@ void *gsi_trans_pool_alloc_dma(struct gsi_trans_pool *pool, dma_addr_t *addr)
return pool->base + offset;
}
/* Return the pool element that immediately follows the one given.
* This only works done if elements are allocated one at a time.
*/
void *gsi_trans_pool_next(struct gsi_trans_pool *pool, void *element)
/* Map a TRE ring entry index to the transaction it is associated with */
static void gsi_trans_map(struct gsi_trans *trans, u32 index)
{
void *end = pool->base + pool->count * pool->size;
WARN_ON(element < pool->base);
WARN_ON(element >= end);
WARN_ON(pool->max_alloc != 1);
element += pool->size;
struct gsi_channel *channel = &trans->gsi->channel[trans->channel_id];
return element < end ? element : pool->base;
}
/* The completion event will indicate the last TRE used */
index += trans->used_count - 1;
/* Map a given ring entry index to the transaction associated with it */
static void gsi_channel_trans_map(struct gsi_channel *channel, u32 index,
struct gsi_trans *trans)
{
/* Note: index *must* be used modulo the ring count here */
channel->trans_info.map[index % channel->tre_ring.count] = trans;
}
......@@ -584,15 +572,15 @@ static void __gsi_trans_commit(struct gsi_trans *trans, bool ring_db)
gsi_trans_tre_fill(dest_tre, addr, len, last_tre, bei, opcode);
dest_tre++;
}
/* Associate the TRE with the transaction */
gsi_trans_map(trans, tre_ring->index);
tre_ring->index += trans->used_count;
trans->len = byte_count;
if (channel->toward_ipa)
gsi_trans_tx_committed(trans);
/* Associate the last TRE with the transaction */
gsi_channel_trans_map(channel, tre_ring->index - 1, trans);
gsi_trans_move_pending(trans);
/* Ring doorbell if requested, or if all TREs are allocated */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment