Commit e91b3b61 authored by David S. Miller's avatar David S. Miller

Merge branch 'ipa-simplify-completion-stats'

Alex Elder says:

====================
net: ipa: simplify completion statistics

The first patch in this series makes the name used for variables
representing a TRE ring be consistent everywhere.  The second
renames two structure fields to better represent their purpose.

The last four rework a little code that manages some tranaction and
byte transfer statistics maintained mainly for TX endpoints.  For
the most part this series is refactoring.  The last one also
includes the first step toward no longer assuming an event ring is
dedicated to a single channel.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5cb3ab50 c5bddecb
...@@ -991,6 +991,17 @@ void gsi_resume(struct gsi *gsi) ...@@ -991,6 +991,17 @@ void gsi_resume(struct gsi *gsi)
enable_irq(gsi->irq); enable_irq(gsi->irq);
} }
void gsi_trans_tx_committed(struct gsi_trans *trans)
{
struct gsi_channel *channel = &trans->gsi->channel[trans->channel_id];
channel->trans_count++;
channel->byte_count += trans->len;
trans->trans_count = channel->trans_count;
trans->byte_count = channel->byte_count;
}
void gsi_trans_tx_queued(struct gsi_trans *trans) void gsi_trans_tx_queued(struct gsi_trans *trans)
{ {
u32 channel_id = trans->channel_id; u32 channel_id = trans->channel_id;
...@@ -1010,42 +1021,36 @@ void gsi_trans_tx_queued(struct gsi_trans *trans) ...@@ -1010,42 +1021,36 @@ void gsi_trans_tx_queued(struct gsi_trans *trans)
} }
/** /**
* gsi_channel_tx_update() - Report completed TX transfers * gsi_trans_tx_completed() - Report completed TX transactions
* @channel: Channel that has completed transmitting packets * @trans: TX channel transaction that has completed
* @trans: Last transation known to be complete
* *
* Compute the number of transactions and bytes that have been transferred * Report that a transaction on a TX channel has completed. At the time a
* over a TX channel since the given transaction was committed. Report this * transaction is committed, we record *in the transaction* its channel's
* information to the network stack. * committed transaction and byte counts. Transactions are completed in
* order, and the difference between the channel's byte/transaction count
* when the transaction was committed and when it completes tells us
* exactly how much data has been transferred while the transaction was
* pending.
* *
* At the time a transaction is committed, we record its channel's * We report this information to the network stack, which uses it to manage
* committed transaction and byte counts *in the transaction*. * the rate at which data is sent to hardware.
* Completions are signaled by the hardware with an interrupt, and
* we can determine the latest completed transaction at that time.
*
* The difference between the byte/transaction count recorded in
* the transaction and the count last time we recorded a completion
* tells us exactly how much data has been transferred between
* completions.
*
* Calling this each time we learn of a newly-completed transaction
* allows us to provide accurate information to the network stack
* about how much work has been completed by the hardware at a given
* point in time.
*/ */
static void static void gsi_trans_tx_completed(struct gsi_trans *trans)
gsi_channel_tx_update(struct gsi_channel *channel, struct gsi_trans *trans)
{ {
u64 byte_count = trans->byte_count + trans->len; u32 channel_id = trans->channel_id;
u64 trans_count = trans->trans_count + 1; struct gsi *gsi = trans->gsi;
struct gsi_channel *channel;
u32 trans_count;
u32 byte_count;
channel = &gsi->channel[channel_id];
trans_count = trans->trans_count - channel->compl_trans_count;
byte_count = trans->byte_count - channel->compl_byte_count;
byte_count -= channel->compl_byte_count;
channel->compl_byte_count += byte_count;
trans_count -= channel->compl_trans_count;
channel->compl_trans_count += trans_count; channel->compl_trans_count += trans_count;
channel->compl_byte_count += byte_count;
ipa_gsi_channel_tx_completed(channel->gsi, gsi_channel_id(channel), ipa_gsi_channel_tx_completed(gsi, channel_id, trans_count, byte_count);
trans_count, byte_count);
} }
/* Channel control interrupt handler */ /* Channel control interrupt handler */
...@@ -1365,8 +1370,6 @@ static void gsi_evt_ring_rx_update(struct gsi_evt_ring *evt_ring, u32 index) ...@@ -1365,8 +1370,6 @@ static void gsi_evt_ring_rx_update(struct gsi_evt_ring *evt_ring, u32 index)
struct gsi_event *event_done; struct gsi_event *event_done;
struct gsi_event *event; struct gsi_event *event;
struct gsi_trans *trans; struct gsi_trans *trans;
u32 trans_count = 0;
u32 byte_count = 0;
u32 event_avail; u32 event_avail;
u32 old_index; u32 old_index;
...@@ -1390,8 +1393,6 @@ static void gsi_evt_ring_rx_update(struct gsi_evt_ring *evt_ring, u32 index) ...@@ -1390,8 +1393,6 @@ static void gsi_evt_ring_rx_update(struct gsi_evt_ring *evt_ring, u32 index)
event_done = gsi_ring_virt(ring, index); event_done = gsi_ring_virt(ring, index);
do { do {
trans->len = __le16_to_cpu(event->len); trans->len = __le16_to_cpu(event->len);
byte_count += trans->len;
trans_count++;
/* Move on to the next event and transaction */ /* Move on to the next event and transaction */
if (--event_avail) if (--event_avail)
...@@ -1400,10 +1401,6 @@ static void gsi_evt_ring_rx_update(struct gsi_evt_ring *evt_ring, u32 index) ...@@ -1400,10 +1401,6 @@ static void gsi_evt_ring_rx_update(struct gsi_evt_ring *evt_ring, u32 index)
event = gsi_ring_virt(ring, 0); event = gsi_ring_virt(ring, 0);
trans = gsi_trans_pool_next(&trans_info->pool, trans); trans = gsi_trans_pool_next(&trans_info->pool, trans);
} while (event != event_done); } while (event != event_done);
/* We record RX bytes when they are received */
channel->byte_count += byte_count;
channel->trans_count += trans_count;
} }
/* Initialize a ring, including allocating DMA memory for its entries */ /* Initialize a ring, including allocating DMA memory for its entries */
...@@ -1503,7 +1500,7 @@ static struct gsi_trans *gsi_channel_update(struct gsi_channel *channel) ...@@ -1503,7 +1500,7 @@ static struct gsi_trans *gsi_channel_update(struct gsi_channel *channel)
* up the network stack. * up the network stack.
*/ */
if (channel->toward_ipa) if (channel->toward_ipa)
gsi_channel_tx_update(channel, trans); gsi_trans_tx_completed(trans);
else else
gsi_evt_ring_rx_update(evt_ring, index); gsi_evt_ring_rx_update(evt_ring, index);
......
...@@ -117,9 +117,9 @@ struct gsi_channel { ...@@ -117,9 +117,9 @@ struct gsi_channel {
struct gsi_ring tre_ring; struct gsi_ring tre_ring;
u32 evt_ring_id; u32 evt_ring_id;
/* The following counts are used only for TX endpoints */
u64 byte_count; /* total # bytes transferred */ u64 byte_count; /* total # bytes transferred */
u64 trans_count; /* total # transactions */ u64 trans_count; /* total # transactions */
/* The following counts are used only for TX endpoints */
u64 queued_byte_count; /* last reported queued byte count */ u64 queued_byte_count; /* last reported queued byte count */
u64 queued_trans_count; /* ...and queued trans count */ u64 queued_trans_count; /* ...and queued trans count */
u64 compl_byte_count; /* last reported completed byte count */ u64 compl_byte_count; /* last reported completed byte count */
......
...@@ -104,6 +104,15 @@ void gsi_channel_doorbell(struct gsi_channel *channel); ...@@ -104,6 +104,15 @@ void gsi_channel_doorbell(struct gsi_channel *channel);
*/ */
void *gsi_ring_virt(struct gsi_ring *ring, u32 index); void *gsi_ring_virt(struct gsi_ring *ring, u32 index);
/**
* gsi_trans_tx_committed() - Record bytes committed for transmit
* @trans: TX endpoint transaction being committed
*
* Report that a TX transaction has been committed. It updates some
* statistics used to manage transmit rates.
*/
void gsi_trans_tx_committed(struct gsi_trans *trans);
/** /**
* gsi_trans_tx_queued() - Report a queued TX channel transaction * gsi_trans_tx_queued() - Report a queued TX channel transaction
* @trans: Transaction being passed to hardware * @trans: Transaction being passed to hardware
......
...@@ -355,7 +355,7 @@ struct gsi_trans *gsi_channel_trans_alloc(struct gsi *gsi, u32 channel_id, ...@@ -355,7 +355,7 @@ struct gsi_trans *gsi_channel_trans_alloc(struct gsi *gsi, u32 channel_id,
trans = gsi_trans_pool_alloc(&trans_info->pool, 1); trans = gsi_trans_pool_alloc(&trans_info->pool, 1);
trans->gsi = gsi; trans->gsi = gsi;
trans->channel_id = channel_id; trans->channel_id = channel_id;
trans->tre_count = tre_count; trans->rsvd_count = tre_count;
init_completion(&trans->completion); init_completion(&trans->completion);
/* Allocate the scatterlist and (if requested) info entries. */ /* Allocate the scatterlist and (if requested) info entries. */
...@@ -405,17 +405,17 @@ void gsi_trans_free(struct gsi_trans *trans) ...@@ -405,17 +405,17 @@ void gsi_trans_free(struct gsi_trans *trans)
/* Releasing the reserved TREs implicitly frees the sgl[] and /* Releasing the reserved TREs implicitly frees the sgl[] and
* (if present) info[] arrays, plus the transaction itself. * (if present) info[] arrays, plus the transaction itself.
*/ */
gsi_trans_tre_release(trans_info, trans->tre_count); gsi_trans_tre_release(trans_info, trans->rsvd_count);
} }
/* Add an immediate command to a transaction */ /* Add an immediate command to a transaction */
void gsi_trans_cmd_add(struct gsi_trans *trans, void *buf, u32 size, void gsi_trans_cmd_add(struct gsi_trans *trans, void *buf, u32 size,
dma_addr_t addr, enum ipa_cmd_opcode opcode) dma_addr_t addr, enum ipa_cmd_opcode opcode)
{ {
u32 which = trans->used++; u32 which = trans->used_count++;
struct scatterlist *sg; struct scatterlist *sg;
WARN_ON(which >= trans->tre_count); WARN_ON(which >= trans->rsvd_count);
/* Commands are quite different from data transfer requests. /* Commands are quite different from data transfer requests.
* Their payloads come from a pool whose memory is allocated * Their payloads come from a pool whose memory is allocated
...@@ -446,9 +446,9 @@ int gsi_trans_page_add(struct gsi_trans *trans, struct page *page, u32 size, ...@@ -446,9 +446,9 @@ int gsi_trans_page_add(struct gsi_trans *trans, struct page *page, u32 size,
struct scatterlist *sg = &trans->sgl[0]; struct scatterlist *sg = &trans->sgl[0];
int ret; int ret;
if (WARN_ON(trans->tre_count != 1)) if (WARN_ON(trans->rsvd_count != 1))
return -EINVAL; return -EINVAL;
if (WARN_ON(trans->used)) if (WARN_ON(trans->used_count))
return -EINVAL; return -EINVAL;
sg_set_page(sg, page, size, offset); sg_set_page(sg, page, size, offset);
...@@ -456,7 +456,7 @@ int gsi_trans_page_add(struct gsi_trans *trans, struct page *page, u32 size, ...@@ -456,7 +456,7 @@ int gsi_trans_page_add(struct gsi_trans *trans, struct page *page, u32 size,
if (!ret) if (!ret)
return -ENOMEM; return -ENOMEM;
trans->used++; /* Transaction now owns the (DMA mapped) page */ trans->used_count++; /* Transaction now owns the (DMA mapped) page */
return 0; return 0;
} }
...@@ -465,25 +465,26 @@ int gsi_trans_page_add(struct gsi_trans *trans, struct page *page, u32 size, ...@@ -465,25 +465,26 @@ int gsi_trans_page_add(struct gsi_trans *trans, struct page *page, u32 size,
int gsi_trans_skb_add(struct gsi_trans *trans, struct sk_buff *skb) int gsi_trans_skb_add(struct gsi_trans *trans, struct sk_buff *skb)
{ {
struct scatterlist *sg = &trans->sgl[0]; struct scatterlist *sg = &trans->sgl[0];
u32 used; u32 used_count;
int ret; int ret;
if (WARN_ON(trans->tre_count != 1)) if (WARN_ON(trans->rsvd_count != 1))
return -EINVAL; return -EINVAL;
if (WARN_ON(trans->used)) if (WARN_ON(trans->used_count))
return -EINVAL; return -EINVAL;
/* skb->len will not be 0 (checked early) */ /* skb->len will not be 0 (checked early) */
ret = skb_to_sgvec(skb, sg, 0, skb->len); ret = skb_to_sgvec(skb, sg, 0, skb->len);
if (ret < 0) if (ret < 0)
return ret; return ret;
used = ret; used_count = ret;
ret = dma_map_sg(trans->gsi->dev, sg, used, trans->direction); ret = dma_map_sg(trans->gsi->dev, sg, used_count, trans->direction);
if (!ret) if (!ret)
return -ENOMEM; return -ENOMEM;
trans->used += used; /* Transaction now owns the (DMA mapped) skb */ /* Transaction now owns the (DMA mapped) skb */
trans->used_count += used_count;
return 0; return 0;
} }
...@@ -549,7 +550,7 @@ static void gsi_trans_tre_fill(struct gsi_tre *dest_tre, dma_addr_t addr, ...@@ -549,7 +550,7 @@ static void gsi_trans_tre_fill(struct gsi_tre *dest_tre, dma_addr_t addr,
static void __gsi_trans_commit(struct gsi_trans *trans, bool ring_db) static void __gsi_trans_commit(struct gsi_trans *trans, bool ring_db)
{ {
struct gsi_channel *channel = &trans->gsi->channel[trans->channel_id]; struct gsi_channel *channel = &trans->gsi->channel[trans->channel_id];
struct gsi_ring *ring = &channel->tre_ring; struct gsi_ring *tre_ring = &channel->tre_ring;
enum ipa_cmd_opcode opcode = IPA_CMD_NONE; enum ipa_cmd_opcode opcode = IPA_CMD_NONE;
bool bei = channel->toward_ipa; bool bei = channel->toward_ipa;
struct gsi_tre *dest_tre; struct gsi_tre *dest_tre;
...@@ -559,7 +560,7 @@ static void __gsi_trans_commit(struct gsi_trans *trans, bool ring_db) ...@@ -559,7 +560,7 @@ static void __gsi_trans_commit(struct gsi_trans *trans, bool ring_db)
u32 avail; u32 avail;
u32 i; u32 i;
WARN_ON(!trans->used); WARN_ON(!trans->used_count);
/* Consume the entries. If we cross the end of the ring while /* Consume the entries. If we cross the end of the ring while
* filling them we'll switch to the beginning to finish. * filling them we'll switch to the beginning to finish.
...@@ -567,35 +568,30 @@ static void __gsi_trans_commit(struct gsi_trans *trans, bool ring_db) ...@@ -567,35 +568,30 @@ static void __gsi_trans_commit(struct gsi_trans *trans, bool ring_db)
* transfer request, whose opcode is IPA_CMD_NONE. * transfer request, whose opcode is IPA_CMD_NONE.
*/ */
cmd_opcode = channel->command ? &trans->cmd_opcode[0] : NULL; cmd_opcode = channel->command ? &trans->cmd_opcode[0] : NULL;
avail = ring->count - ring->index % ring->count; avail = tre_ring->count - tre_ring->index % tre_ring->count;
dest_tre = gsi_ring_virt(ring, ring->index); dest_tre = gsi_ring_virt(tre_ring, tre_ring->index);
for_each_sg(trans->sgl, sg, trans->used, i) { for_each_sg(trans->sgl, sg, trans->used_count, i) {
bool last_tre = i == trans->used - 1; bool last_tre = i == trans->used_count - 1;
dma_addr_t addr = sg_dma_address(sg); dma_addr_t addr = sg_dma_address(sg);
u32 len = sg_dma_len(sg); u32 len = sg_dma_len(sg);
byte_count += len; byte_count += len;
if (!avail--) if (!avail--)
dest_tre = gsi_ring_virt(ring, 0); dest_tre = gsi_ring_virt(tre_ring, 0);
if (cmd_opcode) if (cmd_opcode)
opcode = *cmd_opcode++; opcode = *cmd_opcode++;
gsi_trans_tre_fill(dest_tre, addr, len, last_tre, bei, opcode); gsi_trans_tre_fill(dest_tre, addr, len, last_tre, bei, opcode);
dest_tre++; dest_tre++;
} }
ring->index += trans->used; tre_ring->index += trans->used_count;
if (channel->toward_ipa) { trans->len = byte_count;
/* We record TX bytes when they are sent */ if (channel->toward_ipa)
trans->len = byte_count; gsi_trans_tx_committed(trans);
trans->trans_count = channel->trans_count;
trans->byte_count = channel->byte_count;
channel->trans_count++;
channel->byte_count += byte_count;
}
/* Associate the last TRE with the transaction */ /* Associate the last TRE with the transaction */
gsi_channel_trans_map(channel, ring->index - 1, trans); gsi_channel_trans_map(channel, tre_ring->index - 1, trans);
gsi_trans_move_pending(trans); gsi_trans_move_pending(trans);
...@@ -611,7 +607,7 @@ static void __gsi_trans_commit(struct gsi_trans *trans, bool ring_db) ...@@ -611,7 +607,7 @@ static void __gsi_trans_commit(struct gsi_trans *trans, bool ring_db)
/* Commit a GSI transaction */ /* Commit a GSI transaction */
void gsi_trans_commit(struct gsi_trans *trans, bool ring_db) void gsi_trans_commit(struct gsi_trans *trans, bool ring_db)
{ {
if (trans->used) if (trans->used_count)
__gsi_trans_commit(trans, ring_db); __gsi_trans_commit(trans, ring_db);
else else
gsi_trans_free(trans); gsi_trans_free(trans);
...@@ -620,7 +616,7 @@ void gsi_trans_commit(struct gsi_trans *trans, bool ring_db) ...@@ -620,7 +616,7 @@ void gsi_trans_commit(struct gsi_trans *trans, bool ring_db)
/* Commit a GSI transaction and wait for it to complete */ /* Commit a GSI transaction and wait for it to complete */
void gsi_trans_commit_wait(struct gsi_trans *trans) void gsi_trans_commit_wait(struct gsi_trans *trans)
{ {
if (!trans->used) if (!trans->used_count)
goto out_trans_free; goto out_trans_free;
refcount_inc(&trans->refcount); refcount_inc(&trans->refcount);
...@@ -638,7 +634,7 @@ void gsi_trans_complete(struct gsi_trans *trans) ...@@ -638,7 +634,7 @@ void gsi_trans_complete(struct gsi_trans *trans)
{ {
/* If the entire SGL was mapped when added, unmap it now */ /* If the entire SGL was mapped when added, unmap it now */
if (trans->direction != DMA_NONE) if (trans->direction != DMA_NONE)
dma_unmap_sg(trans->gsi->dev, trans->sgl, trans->used, dma_unmap_sg(trans->gsi->dev, trans->sgl, trans->used_count,
trans->direction); trans->direction);
ipa_gsi_trans_complete(trans); ipa_gsi_trans_complete(trans);
...@@ -675,7 +671,7 @@ void gsi_channel_trans_cancel_pending(struct gsi_channel *channel) ...@@ -675,7 +671,7 @@ void gsi_channel_trans_cancel_pending(struct gsi_channel *channel)
int gsi_trans_read_byte(struct gsi *gsi, u32 channel_id, dma_addr_t addr) int gsi_trans_read_byte(struct gsi *gsi, u32 channel_id, dma_addr_t addr)
{ {
struct gsi_channel *channel = &gsi->channel[channel_id]; struct gsi_channel *channel = &gsi->channel[channel_id];
struct gsi_ring *ring = &channel->tre_ring; struct gsi_ring *tre_ring = &channel->tre_ring;
struct gsi_trans_info *trans_info; struct gsi_trans_info *trans_info;
struct gsi_tre *dest_tre; struct gsi_tre *dest_tre;
...@@ -687,10 +683,10 @@ int gsi_trans_read_byte(struct gsi *gsi, u32 channel_id, dma_addr_t addr) ...@@ -687,10 +683,10 @@ int gsi_trans_read_byte(struct gsi *gsi, u32 channel_id, dma_addr_t addr)
/* Now fill the the reserved TRE and tell the hardware */ /* Now fill the the reserved TRE and tell the hardware */
dest_tre = gsi_ring_virt(ring, ring->index); dest_tre = gsi_ring_virt(tre_ring, tre_ring->index);
gsi_trans_tre_fill(dest_tre, addr, 1, true, false, IPA_CMD_NONE); gsi_trans_tre_fill(dest_tre, addr, 1, true, false, IPA_CMD_NONE);
ring->index++; tre_ring->index++;
gsi_channel_doorbell(channel); gsi_channel_doorbell(channel);
return 0; return 0;
......
...@@ -33,9 +33,9 @@ struct gsi_trans_pool; ...@@ -33,9 +33,9 @@ struct gsi_trans_pool;
* @gsi: GSI pointer * @gsi: GSI pointer
* @channel_id: Channel number transaction is associated with * @channel_id: Channel number transaction is associated with
* @cancelled: If set by the core code, transaction was cancelled * @cancelled: If set by the core code, transaction was cancelled
* @tre_count: Number of TREs reserved for this transaction * @rsvd_count: Number of TREs reserved for this transaction
* @used: Number of TREs *used* (could be less than tre_count) * @used_count: Number of TREs *used* (could be less than rsvd_count)
* @len: Total # of transfer bytes represented in sgl[] (set by core) * @len: Number of bytes sent or received by the transaction
* @data: Preserved but not touched by the core transaction code * @data: Preserved but not touched by the core transaction code
* @cmd_opcode: Array of command opcodes (command channel only) * @cmd_opcode: Array of command opcodes (command channel only)
* @sgl: An array of scatter/gather entries managed by core code * @sgl: An array of scatter/gather entries managed by core code
...@@ -45,8 +45,9 @@ struct gsi_trans_pool; ...@@ -45,8 +45,9 @@ struct gsi_trans_pool;
* @byte_count: TX channel byte count recorded when transaction committed * @byte_count: TX channel byte count recorded when transaction committed
* @trans_count: Channel transaction count when committed (for BQL accounting) * @trans_count: Channel transaction count when committed (for BQL accounting)
* *
* The size used for some fields in this structure were chosen to ensure * The @len field is set when the transaction is committed. For RX
* the full structure size is no larger than 128 bytes. * transactions it is updated later to reflect the actual number of bytes
* received.
*/ */
struct gsi_trans { struct gsi_trans {
struct list_head links; /* gsi_channel lists */ struct list_head links; /* gsi_channel lists */
...@@ -56,8 +57,8 @@ struct gsi_trans { ...@@ -56,8 +57,8 @@ struct gsi_trans {
bool cancelled; /* true if transaction was cancelled */ bool cancelled; /* true if transaction was cancelled */
u8 tre_count; /* # TREs requested */ u8 rsvd_count; /* # TREs requested */
u8 used; /* # entries used in sgl[] */ u8 used_count; /* # entries used in sgl[] */
u32 len; /* total # bytes across sgl[] */ u32 len; /* total # bytes across sgl[] */
union { union {
......
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