unsignedint ef4_tx_max_skb_descs(struct ef4_nic *efx)
{ /* This is probably too much since we don't have any TSO support; *it'saleft-overfromwhenwehadSoftwareTSO.Butit'ssafer *toleaveitas-isthantrytodetermineanewbound.
*/ /* Header and payload descriptor for each output segment, plus *oneforeveryinputfragmentboundarywithinasegment
*/ unsignedint max_descs = EF4_TSO_MAX_SEGS * 2 + MAX_SKB_FRAGS;
/* Possibly one more per segment for the alignment workaround, *orforoptiondescriptors
*/ if (EF4_WORKAROUND_5391(efx))
max_descs += EF4_TSO_MAX_SEGS;
/* Possibly more for PCIe page boundaries within input fragments */ if (PAGE_SIZE > EF4_PAGE_SIZE)
max_descs += max_t(unsignedint, MAX_SKB_FRAGS,
DIV_ROUND_UP(GSO_LEGACY_MAX_SIZE,
EF4_PAGE_SIZE));
return max_descs;
}
staticvoid ef4_tx_maybe_stop_queue(struct ef4_tx_queue *txq1)
{ /* We need to consider both queues that the net core sees as one */ struct ef4_tx_queue *txq2 = ef4_tx_queue_partner(txq1); struct ef4_nic *efx = txq1->efx; unsignedint fill_level;
/* We used the stale old_read_count above, which gives us a *pessimisticestimateofthefilllevel(whichmayeven *validlybe>=efx->txq_entries).Nowtryagainusing *read_count(morelikelytobeacachemiss). * *Ifwereadread_countandthenconditionallystopthe *queue,itispossibleforthecompletionpathtoracewith *usandcompletealloutstandingdescriptorsinthemiddle, *afterwhichtherewillbenomorecompletionstowakeit. *Thereforewestopthequeuefirst,thenreadread_count *(withamemorybarriertoensuretheordering),then *restartthequeueifthefilllevelturnsouttobelow *enough.
*/
netif_tx_stop_queue(txq1->core_txq);
smp_mb();
txq1->old_read_count = READ_ONCE(txq1->read_count);
txq2->old_read_count = READ_ONCE(txq2->read_count);
/* The final descriptor for a fragment is responsible for *unmappingthewholefragment.
*/
buffer->flags = EF4_TX_BUF_CONT | dma_flags;
buffer->unmap_len = unmap_len;
buffer->dma_offset = buffer->dma_addr - unmap_addr;
if (frag_index >= nr_frags) { /* Store SKB details with the final buffer for *thecompletion.
*/
buffer->skb = skb;
buffer->flags = EF4_TX_BUF_SKB | dma_flags; return0;
}
/* Move on to the next fragment. */
fragment = &skb_shinfo(skb)->frags[frag_index++];
len = skb_frag_size(fragment);
dma_addr = skb_frag_dma_map(dma_dev, fragment, 0, len, DMA_TO_DEVICE);
dma_flags = 0;
unmap_len = len;
unmap_addr = dma_addr;
if (unlikely(dma_mapping_error(dma_dev, dma_addr))) return -EIO;
} while (1);
}
/* Remove buffers put into a tx_queue. None of the buffers must have *anskbattached.
*/ staticvoid ef4_enqueue_unwind(struct ef4_tx_queue *tx_queue)
{ struct ef4_tx_buffer *buffer;
/* Work backwards until we hit the original insert pointer value */ while (tx_queue->insert_count != tx_queue->write_count) {
--tx_queue->insert_count;
buffer = __ef4_tx_queue_get_insert_buffer(tx_queue);
ef4_dequeue_buffer(tx_queue, buffer, NULL, NULL);
}
}
/* Pass off to hardware */ if (!netdev_xmit_more() || netif_xmit_stopped(tx_queue->core_txq)) { struct ef4_tx_queue *txq2 = ef4_tx_queue_partner(tx_queue);
/* There could be packets left on the partner queue if those *SKBshadskb->xmit_moreset.Ifwedonotpushthosethey *couldbeleftforalongtimeandcauseanetdevwatchdog.
*/ if (txq2->xmit_more_available)
ef4_nic_push_buffers(txq2);
/* Do not destroy high-priority queues when they become *unused.Wewouldhavetoflushthemfirst,anditis *fairlydifficulttoflushasubsetofTXqueues.Leave *ittoef4_fini_channels().
*/
/* See if we need to restart the netif queue. This memory *barrierensuresthatwewriteread_count(inside *ef4_dequeue_buffers())beforereadingthequeuestatus.
*/
smp_mb(); if (unlikely(netif_tx_queue_stopped(tx_queue->core_txq)) &&
likely(efx->port_enabled) &&
likely(netif_device_present(efx->net_dev))) {
txq2 = ef4_tx_queue_partner(tx_queue);
fill_level = max(tx_queue->insert_count - tx_queue->read_count,
txq2->insert_count - txq2->read_count); if (fill_level <= efx->txq_wake_thresh)
netif_tx_wake_queue(tx_queue->core_txq);
}
/* Check whether the hardware queue is now empty */ if ((int)(tx_queue->read_count - tx_queue->old_write_count) >= 0) {
tx_queue->old_write_count = READ_ONCE(tx_queue->write_count); if (tx_queue->read_count == tx_queue->old_write_count) {
smp_mb();
tx_queue->empty_read_count =
tx_queue->read_count | EF4_EMPTY_COUNT_VALID;
}
}
}
netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev, "shutting down TX queue %d\n", tx_queue->queue);
if (!tx_queue->buffer) return;
/* Free any buffers left in the ring */ while (tx_queue->read_count != tx_queue->write_count) { unsignedint pkts_compl = 0, bytes_compl = 0;
buffer = &tx_queue->buffer[tx_queue->read_count & tx_queue->ptr_mask];
ef4_dequeue_buffer(tx_queue, buffer, &pkts_compl, &bytes_compl);
if (tx_queue->cb_page) { for (i = 0; i < ef4_tx_cb_page_count(tx_queue); i++)
ef4_nic_free_buffer(tx_queue->efx,
&tx_queue->cb_page[i]);
kfree(tx_queue->cb_page);
tx_queue->cb_page = NULL;
}
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.17Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-10-03)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.