diff options
Diffstat (limited to 'drivers/net/ethernet/sfc/ef100_tx.c')
-rw-r--r-- | drivers/net/ethernet/sfc/ef100_tx.c | 44 |
1 files changed, 27 insertions, 17 deletions
diff --git a/drivers/net/ethernet/sfc/ef100_tx.c b/drivers/net/ethernet/sfc/ef100_tx.c index a09546e43408..a90e5a9d2a37 100644 --- a/drivers/net/ethernet/sfc/ef100_tx.c +++ b/drivers/net/ethernet/sfc/ef100_tx.c @@ -27,7 +27,6 @@ int ef100_tx_probe(struct efx_tx_queue *tx_queue) (tx_queue->ptr_mask + 2) * sizeof(efx_oword_t), GFP_KERNEL); - return 0; } void ef100_tx_init(struct efx_tx_queue *tx_queue) @@ -38,7 +37,14 @@ void ef100_tx_init(struct efx_tx_queue *tx_queue) tx_queue->channel->channel - tx_queue->efx->tx_channel_offset); - if (efx_mcdi_tx_init(tx_queue, false)) + /* This value is purely documentational; as EF100 never passes through + * the switch statement in tx.c:__efx_enqueue_skb(), that switch does + * not handle case 3. EF100's TSOv3 descriptors are generated by + * ef100_make_tso_desc(). + * Meanwhile, all efx_mcdi_tx_init() cares about is that it's not 2. + */ + tx_queue->tso_version = 3; + if (efx_mcdi_tx_init(tx_queue)) netdev_WARN(tx_queue->efx->net_dev, "failed to initialise TXQ %d\n", tx_queue->queue); } @@ -117,11 +123,13 @@ static efx_oword_t *ef100_tx_desc(struct efx_tx_queue *tx_queue, unsigned int in return NULL; } -void ef100_notify_tx_desc(struct efx_tx_queue *tx_queue) +static void ef100_notify_tx_desc(struct efx_tx_queue *tx_queue) { unsigned int write_ptr; efx_dword_t reg; + tx_queue->xmit_pending = false; + if (unlikely(tx_queue->notify_count == tx_queue->write_count)) return; @@ -131,7 +139,6 @@ void ef100_notify_tx_desc(struct efx_tx_queue *tx_queue) efx_writed_page(tx_queue->efx, ®, ER_GZ_TX_RING_DOORBELL, tx_queue->queue); tx_queue->notify_count = tx_queue->write_count; - tx_queue->xmit_more_available = false; } static void ef100_tx_push_buffers(struct efx_tx_queue *tx_queue) @@ -359,28 +366,31 @@ int ef100_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb) goto err; ef100_tx_make_descriptors(tx_queue, skb, segments); - fill_level = efx_channel_tx_fill_level(tx_queue->channel); + fill_level = efx_channel_tx_old_fill_level(tx_queue->channel); if (fill_level > efx->txq_stop_thresh) { + struct efx_tx_queue *txq2; + netif_tx_stop_queue(tx_queue->core_txq); /* Re-read after a memory barrier in case we've raced with * the completion path. Otherwise there's a danger we'll never * restart the queue if all completions have just happened. */ smp_mb(); - fill_level = efx_channel_tx_fill_level(tx_queue->channel); + efx_for_each_channel_tx_queue(txq2, tx_queue->channel) + txq2->old_read_count = READ_ONCE(txq2->read_count); + fill_level = efx_channel_tx_old_fill_level(tx_queue->channel); if (fill_level < efx->txq_stop_thresh) netif_tx_start_queue(tx_queue->core_txq); } - if (__netdev_tx_sent_queue(tx_queue->core_txq, skb->len, xmit_more)) - tx_queue->xmit_more_available = false; /* push doorbell */ - else if (tx_queue->write_count - tx_queue->notify_count > 255) - /* Ensure we never push more than 256 packets at once */ - tx_queue->xmit_more_available = false; /* push */ - else - tx_queue->xmit_more_available = true; /* don't push yet */ + tx_queue->xmit_pending = true; - if (!tx_queue->xmit_more_available) + /* If xmit_more then we don't need to push the doorbell, unless there + * are 256 descriptors already queued in which case we have to push to + * ensure we never push more than 256 at once. + */ + if (__netdev_tx_sent_queue(tx_queue->core_txq, skb->len, xmit_more) || + tx_queue->write_count - tx_queue->notify_count > 255) ef100_tx_push_buffers(tx_queue); if (segments) { @@ -399,10 +409,10 @@ err: /* If we're not expecting another transmit and we had something to push * on this queue then we need to push here to get the previous packets - * out. We only enter this branch from before the 'Update BQL' section - * above, so xmit_more_available still refers to the old state. + * out. We only enter this branch from before the xmit_more handling + * above, so xmit_pending still refers to the old state. */ - if (tx_queue->xmit_more_available && !xmit_more) + if (tx_queue->xmit_pending && !xmit_more) ef100_tx_push_buffers(tx_queue); return rc; } |