diff --git a/drivers/net/ipa/gsi.c b/drivers/net/ipa/gsi.c index 5b446d2a07c8..df8af1f00fc8 100644 --- a/drivers/net/ipa/gsi.c +++ b/drivers/net/ipa/gsi.c @@ -991,6 +991,17 @@ void gsi_resume(struct gsi *gsi) 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) { u32 channel_id = trans->channel_id; @@ -1010,42 +1021,36 @@ void gsi_trans_tx_queued(struct gsi_trans *trans) } /** - * gsi_channel_tx_update() - Report completed TX transfers - * @channel: Channel that has completed transmitting packets - * @trans: Last transation known to be complete + * gsi_trans_tx_completed() - Report completed TX transactions + * @trans: TX channel transaction that has completed * - * Compute the number of transactions and bytes that have been transferred - * over a TX channel since the given transaction was committed. Report this - * information to the network stack. + * Report that a transaction on a TX channel has completed. At the time a + * transaction is committed, we record *in the transaction* its channel's + * 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 - * committed transaction and byte counts *in the transaction*. - * 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. + * We report this information to the network stack, which uses it to manage + * the rate at which data is sent to hardware. */ -static void -gsi_channel_tx_update(struct gsi_channel *channel, struct gsi_trans *trans) +static void gsi_trans_tx_completed(struct gsi_trans *trans) { - u64 byte_count = trans->byte_count + trans->len; - u64 trans_count = trans->trans_count + 1; + u32 channel_id = trans->channel_id; + 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_byte_count += byte_count; - ipa_gsi_channel_tx_completed(channel->gsi, gsi_channel_id(channel), - trans_count, byte_count); + ipa_gsi_channel_tx_completed(gsi, channel_id, trans_count, byte_count); } /* Channel control interrupt handler */ @@ -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; struct gsi_trans *trans; - u32 trans_count = 0; - u32 byte_count = 0; u32 event_avail; u32 old_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); do { trans->len = __le16_to_cpu(event->len); - byte_count += trans->len; - trans_count++; /* Move on to the next event and transaction */ if (--event_avail) @@ -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); trans = gsi_trans_pool_next(&trans_info->pool, trans); } 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 */ @@ -1503,7 +1500,7 @@ static struct gsi_trans *gsi_channel_update(struct gsi_channel *channel) * up the network stack. */ if (channel->toward_ipa) - gsi_channel_tx_update(channel, trans); + gsi_trans_tx_completed(trans); else gsi_evt_ring_rx_update(evt_ring, index); diff --git a/drivers/net/ipa/gsi.h b/drivers/net/ipa/gsi.h index 89dac7fc8c4c..bad1a78a96ed 100644 --- a/drivers/net/ipa/gsi.h +++ b/drivers/net/ipa/gsi.h @@ -117,9 +117,9 @@ struct gsi_channel { struct gsi_ring tre_ring; u32 evt_ring_id; + /* The following counts are used only for TX endpoints */ u64 byte_count; /* total # bytes transferred */ 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_trans_count; /* ...and queued trans count */ u64 compl_byte_count; /* last reported completed byte count */ diff --git a/drivers/net/ipa/gsi_private.h b/drivers/net/ipa/gsi_private.h index 56450a189907..74cbc287fc71 100644 --- a/drivers/net/ipa/gsi_private.h +++ b/drivers/net/ipa/gsi_private.h @@ -104,6 +104,15 @@ void gsi_channel_doorbell(struct gsi_channel *channel); */ 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 * @trans: Transaction being passed to hardware diff --git a/drivers/net/ipa/gsi_trans.c b/drivers/net/ipa/gsi_trans.c index 278e467c5430..a110be72f70b 100644 --- a/drivers/net/ipa/gsi_trans.c +++ b/drivers/net/ipa/gsi_trans.c @@ -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 = gsi; trans->channel_id = channel_id; - trans->tre_count = tre_count; + trans->rsvd_count = tre_count; init_completion(&trans->completion); /* Allocate the scatterlist and (if requested) info entries. */ @@ -405,17 +405,17 @@ void gsi_trans_free(struct gsi_trans *trans) /* Releasing the reserved TREs implicitly frees the sgl[] and * (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 */ void gsi_trans_cmd_add(struct gsi_trans *trans, void *buf, u32 size, dma_addr_t addr, enum ipa_cmd_opcode opcode) { - u32 which = trans->used++; + u32 which = trans->used_count++; struct scatterlist *sg; - WARN_ON(which >= trans->tre_count); + WARN_ON(which >= trans->rsvd_count); /* Commands are quite different from data transfer requests. * 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, struct scatterlist *sg = &trans->sgl[0]; int ret; - if (WARN_ON(trans->tre_count != 1)) + if (WARN_ON(trans->rsvd_count != 1)) return -EINVAL; - if (WARN_ON(trans->used)) + if (WARN_ON(trans->used_count)) return -EINVAL; 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, if (!ret) return -ENOMEM; - trans->used++; /* Transaction now owns the (DMA mapped) page */ + trans->used_count++; /* Transaction now owns the (DMA mapped) page */ return 0; } @@ -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) { struct scatterlist *sg = &trans->sgl[0]; - u32 used; + u32 used_count; int ret; - if (WARN_ON(trans->tre_count != 1)) + if (WARN_ON(trans->rsvd_count != 1)) return -EINVAL; - if (WARN_ON(trans->used)) + if (WARN_ON(trans->used_count)) return -EINVAL; /* skb->len will not be 0 (checked early) */ ret = skb_to_sgvec(skb, sg, 0, skb->len); if (ret < 0) 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) 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; } @@ -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) { 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; bool bei = channel->toward_ipa; struct gsi_tre *dest_tre; @@ -559,7 +560,7 @@ static void __gsi_trans_commit(struct gsi_trans *trans, bool ring_db) u32 avail; u32 i; - WARN_ON(!trans->used); + WARN_ON(!trans->used_count); /* Consume the entries. If we cross the end of the ring while * 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) * transfer request, whose opcode is IPA_CMD_NONE. */ cmd_opcode = channel->command ? &trans->cmd_opcode[0] : NULL; - avail = ring->count - ring->index % ring->count; - dest_tre = gsi_ring_virt(ring, ring->index); - for_each_sg(trans->sgl, sg, trans->used, i) { - bool last_tre = i == trans->used - 1; + avail = tre_ring->count - tre_ring->index % tre_ring->count; + dest_tre = gsi_ring_virt(tre_ring, tre_ring->index); + for_each_sg(trans->sgl, sg, trans->used_count, i) { + bool last_tre = i == trans->used_count - 1; dma_addr_t addr = sg_dma_address(sg); u32 len = sg_dma_len(sg); byte_count += len; if (!avail--) - dest_tre = gsi_ring_virt(ring, 0); + dest_tre = gsi_ring_virt(tre_ring, 0); if (cmd_opcode) opcode = *cmd_opcode++; gsi_trans_tre_fill(dest_tre, addr, len, last_tre, bei, opcode); dest_tre++; } - ring->index += trans->used; + tre_ring->index += trans->used_count; - if (channel->toward_ipa) { - /* We record TX bytes when they are sent */ - trans->len = byte_count; - trans->trans_count = channel->trans_count; - trans->byte_count = channel->byte_count; - channel->trans_count++; - channel->byte_count += byte_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, ring->index - 1, trans); + gsi_channel_trans_map(channel, tre_ring->index - 1, trans); gsi_trans_move_pending(trans); @@ -611,7 +607,7 @@ static void __gsi_trans_commit(struct gsi_trans *trans, bool ring_db) /* Commit a GSI transaction */ void gsi_trans_commit(struct gsi_trans *trans, bool ring_db) { - if (trans->used) + if (trans->used_count) __gsi_trans_commit(trans, ring_db); else gsi_trans_free(trans); @@ -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 */ void gsi_trans_commit_wait(struct gsi_trans *trans) { - if (!trans->used) + if (!trans->used_count) goto out_trans_free; refcount_inc(&trans->refcount); @@ -638,7 +634,7 @@ void gsi_trans_complete(struct gsi_trans *trans) { /* If the entire SGL was mapped when added, unmap it now */ 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); ipa_gsi_trans_complete(trans); @@ -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) { 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_tre *dest_tre; @@ -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 */ - 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); - ring->index++; + tre_ring->index++; gsi_channel_doorbell(channel); return 0; diff --git a/drivers/net/ipa/gsi_trans.h b/drivers/net/ipa/gsi_trans.h index 020c3b32de1d..7084507830c2 100644 --- a/drivers/net/ipa/gsi_trans.h +++ b/drivers/net/ipa/gsi_trans.h @@ -33,9 +33,9 @@ struct gsi_trans_pool; * @gsi: GSI pointer * @channel_id: Channel number transaction is associated with * @cancelled: If set by the core code, transaction was cancelled - * @tre_count: Number of TREs reserved for this transaction - * @used: Number of TREs *used* (could be less than tre_count) - * @len: Total # of transfer bytes represented in sgl[] (set by core) + * @rsvd_count: Number of TREs reserved for this transaction + * @used_count: Number of TREs *used* (could be less than rsvd_count) + * @len: Number of bytes sent or received by the transaction * @data: Preserved but not touched by the core transaction code * @cmd_opcode: Array of command opcodes (command channel only) * @sgl: An array of scatter/gather entries managed by core code @@ -45,8 +45,9 @@ struct gsi_trans_pool; * @byte_count: TX channel byte count recorded when transaction committed * @trans_count: Channel transaction count when committed (for BQL accounting) * - * The size used for some fields in this structure were chosen to ensure - * the full structure size is no larger than 128 bytes. + * The @len field is set when the transaction is committed. For RX + * transactions it is updated later to reflect the actual number of bytes + * received. */ struct gsi_trans { struct list_head links; /* gsi_channel lists */ @@ -56,8 +57,8 @@ struct gsi_trans { bool cancelled; /* true if transaction was cancelled */ - u8 tre_count; /* # TREs requested */ - u8 used; /* # entries used in sgl[] */ + u8 rsvd_count; /* # TREs requested */ + u8 used_count; /* # entries used in sgl[] */ u32 len; /* total # bytes across sgl[] */ union {