// SPDX-License-Identifier: GPL-2.0-only /**************************************************************************** * Driver for Solarflare network controllers and boards * Copyright 2005-2006 Fen Systems Ltd. * Copyright 2005-2015 Solarflare Communications Inc. */ #include <linux/pci.h> #include <linux/tcp.h> #include <linux/ip.h> #include <linux/in.h> #include <linux/ipv6.h> #include <linux/slab.h> #include <net/ipv6.h> #include <linux/if_ether.h> #include <linux/highmem.h> #include <linux/moduleparam.h> #include <linux/cache.h> #include "net_driver.h" #include "efx.h" #include "io.h" #include "nic.h" #include "tx.h" #include "workarounds.h" #include "ef10_regs.h" /* Efx legacy TCP segmentation acceleration. * * Utilises firmware support to go faster than GSO (but not as fast as TSOv2). * * Requires TX checksum offload support. */ #define PTR_DIFF(p1, p2) … /** * struct tso_state - TSO state for an SKB * @out_len: Remaining length in current segment * @seqnum: Current sequence number * @ipv4_id: Current IPv4 ID, host endian * @packet_space: Remaining space in current packet * @dma_addr: DMA address of current position * @in_len: Remaining length in current SKB fragment * @unmap_len: Length of SKB fragment * @unmap_addr: DMA address of SKB fragment * @protocol: Network protocol (after any VLAN header) * @ip_off: Offset of IP header * @tcp_off: Offset of TCP header * @header_len: Number of bytes of header * @ip_base_len: IPv4 tot_len or IPv6 payload_len, before TCP payload * @header_dma_addr: Header DMA address * @header_unmap_len: Header DMA mapped length * * The state used during segmentation. It is put into this data structure * just to make it easy to pass into inline functions. */ struct tso_state { … }; static inline void prefetch_ptr(struct efx_tx_queue *tx_queue) { … } /** * efx_tx_queue_insert - push descriptors onto the TX queue * @tx_queue: Efx TX queue * @dma_addr: DMA address of fragment * @len: Length of fragment * @final_buffer: The final buffer inserted into the queue * * Push descriptors onto the TX queue. */ static void efx_tx_queue_insert(struct efx_tx_queue *tx_queue, dma_addr_t dma_addr, unsigned int len, struct efx_tx_buffer **final_buffer) { … } /* * Verify that our various assumptions about sk_buffs and the conditions * under which TSO will be attempted hold true. Return the protocol number. */ static __be16 efx_tso_check_protocol(struct sk_buff *skb) { … } /* Parse the SKB header and initialise state. */ static int tso_start(struct tso_state *st, struct efx_nic *efx, struct efx_tx_queue *tx_queue, const struct sk_buff *skb) { … } static int tso_get_fragment(struct tso_state *st, struct efx_nic *efx, skb_frag_t *frag) { … } /** * tso_fill_packet_with_fragment - form descriptors for the current fragment * @tx_queue: Efx TX queue * @skb: Socket buffer * @st: TSO state * * Form descriptors for the current fragment, until we reach the end * of fragment or end-of-packet. */ static void tso_fill_packet_with_fragment(struct efx_tx_queue *tx_queue, const struct sk_buff *skb, struct tso_state *st) { … } #define TCP_FLAGS_OFFSET … /** * tso_start_new_packet - generate a new header and prepare for the new packet * @tx_queue: Efx TX queue * @skb: Socket buffer * @st: TSO state * * Generate a new header and prepare for the new packet. Return 0 on * success, or -%ENOMEM if failed to alloc header, or other negative error. */ static int tso_start_new_packet(struct efx_tx_queue *tx_queue, const struct sk_buff *skb, struct tso_state *st) { … } /** * efx_enqueue_skb_tso - segment and transmit a TSO socket buffer * @tx_queue: Efx TX queue * @skb: Socket buffer * @data_mapped: Did we map the data? Always set to true * by this on success. * * Context: You must hold netif_tx_lock() to call this function. * * Add socket buffer @skb to @tx_queue, doing TSO or return != 0 if * @skb was not enqueued. @skb is consumed unless return value is * %EINVAL. */ int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue, struct sk_buff *skb, bool *data_mapped) { … }