drivers/net/ethernet/sfc/falcon/tx.c
Source file repositories/reference/linux-study-clean/drivers/net/ethernet/sfc/falcon/tx.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/net/ethernet/sfc/falcon/tx.c- Extension
.c- Size
- 18265 bytes
- Lines
- 642
- 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
linux/pci.hlinux/tcp.hlinux/ip.hlinux/in.hlinux/ipv6.hlinux/slab.hnet/ipv6.hlinux/if_ether.hlinux/highmem.hlinux/cache.hnet_driver.hefx.hio.hnic.htx.hworkarounds.h
Detected Declarations
function ef4_dequeue_bufferfunction ef4_tx_max_skb_descsfunction ef4_tx_maybe_stop_queuefunction ef4_enqueue_skb_copyfunction ef4_tx_map_datafunction ef4_enqueue_unwindfunction netif_tx_lockfunction ef4_dequeue_buffersfunction ef4_hard_start_xmitfunction ef4_init_tx_queue_core_txqfunction ef4_setup_tcfunction ef4_xmit_donefunction likelyfunction ef4_tx_cb_page_countfunction ef4_probe_tx_queuefunction ef4_init_tx_queuefunction ef4_fini_tx_queuefunction ef4_remove_tx_queue
Annotated Snippet
if (frag_index >= nr_frags) {
/* Store SKB details with the final buffer for
* the completion.
*/
buffer->skb = skb;
buffer->flags = EF4_TX_BUF_SKB | dma_flags;
return 0;
}
/* 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
* an skb attached.
*/
static void 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);
}
}
/*
* Add a socket buffer to a TX queue
*
* This maps all fragments of a socket buffer for DMA and adds them to
* the TX queue. The queue's insert pointer will be incremented by
* the number of fragments in the socket buffer.
*
* If any DMA mapping fails, any mapped fragments will be unmapped,
* the queue's insert pointer will be restored to its original value.
*
* This function is split out from ef4_hard_start_xmit to allow the
* loopback test to direct packets via specific TX queues.
*
* Returns NETDEV_TX_OK.
* You must hold netif_tx_lock() to call this function.
*/
netdev_tx_t ef4_enqueue_skb(struct ef4_tx_queue *tx_queue, struct sk_buff *skb)
{
bool data_mapped = false;
unsigned int skb_len;
skb_len = skb->len;
EF4_WARN_ON_PARANOID(skb_is_gso(skb));
if (skb_len < tx_queue->tx_min_size ||
(skb->data_len && skb_len <= EF4_TX_CB_SIZE)) {
/* Pad short packets or coalesce short fragmented packets. */
if (ef4_enqueue_skb_copy(tx_queue, skb))
goto err;
tx_queue->cb_packets++;
data_mapped = true;
}
/* Map for DMA and create descriptors if we haven't done so already. */
if (!data_mapped && (ef4_tx_map_data(tx_queue, skb)))
goto err;
/* Update BQL */
netdev_tx_sent_queue(tx_queue->core_txq, skb_len);
/* 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
* SKBs had skb->xmit_more set. If we do not push those they
* could be left for a long time and cause a netdev watchdog.
*/
if (txq2->xmit_more_available)
ef4_nic_push_buffers(txq2);
ef4_nic_push_buffers(tx_queue);
Annotation
- Immediate include surface: `linux/pci.h`, `linux/tcp.h`, `linux/ip.h`, `linux/in.h`, `linux/ipv6.h`, `linux/slab.h`, `net/ipv6.h`, `linux/if_ether.h`.
- Detected declarations: `function ef4_dequeue_buffer`, `function ef4_tx_max_skb_descs`, `function ef4_tx_maybe_stop_queue`, `function ef4_enqueue_skb_copy`, `function ef4_tx_map_data`, `function ef4_enqueue_unwind`, `function netif_tx_lock`, `function ef4_dequeue_buffers`, `function ef4_hard_start_xmit`, `function ef4_init_tx_queue_core_txq`.
- 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.