drivers/net/ethernet/sfc/siena/tx_common.c
Source file repositories/reference/linux-study-clean/drivers/net/ethernet/sfc/siena/tx_common.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/net/ethernet/sfc/siena/tx_common.c- Extension
.c- Size
- 12600 bytes
- Lines
- 448
- Domain
- Driver Families
- Bucket
- drivers/net
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
net_driver.hefx.hnic_common.htx_common.hnet/gso.h
Detected Declarations
function efx_tx_cb_page_countfunction efx_siena_probe_tx_queuefunction efx_siena_init_tx_queuefunction efx_siena_remove_tx_queuefunction efx_dequeue_bufferfunction efx_siena_fini_tx_queuefunction efx_dequeue_buffersfunction efx_siena_xmit_done_check_emptyfunction efx_siena_xmit_donefunction likelyfunction efx_siena_enqueue_unwindfunction efx_tx_tso_header_lengthfunction efx_siena_tx_map_datafunction efx_siena_tx_max_skb_descsfunction efx_siena_tx_tso_fallbackfunction skb_list_walk_safe
Annotated Snippet
if (!efx_tx_buffer_in_use(buffer)) {
netif_err(efx, tx_err, efx->net_dev,
"TX queue %d spurious TX completion id %d\n",
tx_queue->queue, read_ptr);
efx_siena_schedule_reset(efx, RESET_TYPE_TX_SKIP);
return;
}
efx_dequeue_buffer(tx_queue, buffer, pkts_compl, bytes_compl);
++tx_queue->read_count;
read_ptr = tx_queue->read_count & tx_queue->ptr_mask;
}
}
void efx_siena_xmit_done_check_empty(struct efx_tx_queue *tx_queue)
{
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) {
/* Ensure that read_count is flushed. */
smp_mb();
tx_queue->empty_read_count =
tx_queue->read_count | EFX_EMPTY_COUNT_VALID;
}
}
}
void efx_siena_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
{
unsigned int fill_level, pkts_compl = 0, bytes_compl = 0;
struct efx_nic *efx = tx_queue->efx;
EFX_WARN_ON_ONCE_PARANOID(index > tx_queue->ptr_mask);
efx_dequeue_buffers(tx_queue, index, &pkts_compl, &bytes_compl);
tx_queue->pkts_compl += pkts_compl;
tx_queue->bytes_compl += bytes_compl;
if (pkts_compl > 1)
++tx_queue->merge_events;
/* See if we need to restart the netif queue. This memory
* barrier ensures that we write read_count (inside
* efx_dequeue_buffers()) before reading the queue status.
*/
smp_mb();
if (unlikely(netif_tx_queue_stopped(tx_queue->core_txq)) &&
likely(efx->port_enabled) &&
likely(netif_device_present(efx->net_dev))) {
fill_level = efx_channel_tx_fill_level(tx_queue->channel);
if (fill_level <= efx->txq_wake_thresh)
netif_tx_wake_queue(tx_queue->core_txq);
}
efx_siena_xmit_done_check_empty(tx_queue);
}
/* Remove buffers put into a tx_queue for the current packet.
* None of the buffers must have an skb attached.
*/
void efx_siena_enqueue_unwind(struct efx_tx_queue *tx_queue,
unsigned int insert_count)
{
struct efx_tx_buffer *buffer;
unsigned int bytes_compl = 0;
unsigned int pkts_compl = 0;
/* Work backwards until we hit the original insert pointer value */
while (tx_queue->insert_count != insert_count) {
--tx_queue->insert_count;
buffer = __efx_tx_queue_get_insert_buffer(tx_queue);
efx_dequeue_buffer(tx_queue, buffer, &pkts_compl, &bytes_compl);
}
}
struct efx_tx_buffer *efx_siena_tx_map_chunk(struct efx_tx_queue *tx_queue,
dma_addr_t dma_addr, size_t len)
{
const struct efx_nic_type *nic_type = tx_queue->efx->type;
struct efx_tx_buffer *buffer;
unsigned int dma_len;
/* Map the fragment taking account of NIC-dependent DMA limits. */
do {
buffer = efx_tx_queue_get_insert_buffer(tx_queue);
if (nic_type->tx_limit_len)
dma_len = nic_type->tx_limit_len(tx_queue, dma_addr, len);
else
Annotation
- Immediate include surface: `net_driver.h`, `efx.h`, `nic_common.h`, `tx_common.h`, `net/gso.h`.
- Detected declarations: `function efx_tx_cb_page_count`, `function efx_siena_probe_tx_queue`, `function efx_siena_init_tx_queue`, `function efx_siena_remove_tx_queue`, `function efx_dequeue_buffer`, `function efx_siena_fini_tx_queue`, `function efx_dequeue_buffers`, `function efx_siena_xmit_done_check_empty`, `function efx_siena_xmit_done`, `function likely`.
- Atlas domain: Driver Families / drivers/net.
- Implementation status: source implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.