blob: da82aabd1d48d55ced66a7d54f79a8d54aaf4996 [file] [edit]
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _TSO_H
#define _TSO_H
#include <linux/skbuff.h>
#include <linux/dma-mapping.h>
#include <net/ip.h>
#define TSO_HEADER_SIZE 256
struct tso_t {
int next_frag_idx;
int size;
void *data;
u16 ip_id;
u8 tlen; /* transport header len */
bool ipv6;
u32 tcp_seq;
};
/* Calculate the worst case buffer count */
static inline int tso_count_descs(const struct sk_buff *skb)
{
return skb_shinfo(skb)->gso_segs * 2 + skb_shinfo(skb)->nr_frags;
}
void tso_build_hdr(const struct sk_buff *skb, char *hdr, struct tso_t *tso,
int size, bool is_last);
void tso_build_data(const struct sk_buff *skb, struct tso_t *tso, int size);
int tso_start(struct sk_buff *skb, struct tso_t *tso);
/**
* struct tso_dma_map - DMA mapping state for GSO payload
* @dev: device used for DMA mapping
* @skb: the GSO skb being mapped
* @hdr_len: per-segment header length
* @iova_state: DMA IOVA state (when IOMMU available)
* @iova_offset: global byte offset into IOVA range (IOVA path only)
* @total_len: total payload length
* @frag_idx: current region (-1 = linear, 0..nr_frags-1 = frag)
* @offset: byte offset within current region
* @linear_dma: DMA address of the linear payload
* @linear_len: length of the linear payload
* @nr_frags: number of frags successfully DMA-mapped
* @frags: per-frag DMA address and length
*
* DMA-maps the payload regions of a GSO skb (linear data + frags).
* Prefers the DMA IOVA API for a single contiguous mapping with one
* IOTLB sync; falls back to per-region dma_map_phys() otherwise.
*/
struct tso_dma_map {
struct device *dev;
const struct sk_buff *skb;
unsigned int hdr_len;
/* IOVA path */
struct dma_iova_state iova_state;
size_t iova_offset;
size_t total_len;
/* Fallback path if IOVA path fails */
int frag_idx;
unsigned int offset;
dma_addr_t linear_dma;
unsigned int linear_len;
unsigned int nr_frags;
struct {
dma_addr_t dma;
unsigned int len;
} frags[MAX_SKB_FRAGS];
};
/**
* struct tso_dma_map_completion_state - Completion-time cleanup state
* @iova_state: DMA IOVA state (when IOMMU available)
* @total_len: total payload length of the IOVA mapping
*
* Drivers store this on their SW ring at xmit time via
* tso_dma_map_completion_save(), then call tso_dma_map_complete() at
* completion time.
*/
struct tso_dma_map_completion_state {
struct dma_iova_state iova_state;
size_t total_len;
};
int tso_dma_map_init(struct tso_dma_map *map, struct device *dev,
const struct sk_buff *skb, unsigned int hdr_len);
void tso_dma_map_cleanup(struct tso_dma_map *map);
unsigned int tso_dma_map_count(struct tso_dma_map *map, unsigned int len);
bool tso_dma_map_next(struct tso_dma_map *map, dma_addr_t *addr,
unsigned int *chunk_len, unsigned int *mapping_len,
unsigned int seg_remaining);
/**
* tso_dma_map_completion_save - save state needed for completion-time cleanup
* @map: the xmit-time DMA map
* @cstate: driver-owned storage that persists until completion
*
* Should be called at xmit time to update the completion state and later passed
* to tso_dma_map_complete().
*/
static inline void
tso_dma_map_completion_save(const struct tso_dma_map *map,
struct tso_dma_map_completion_state *cstate)
{
cstate->iova_state = map->iova_state;
cstate->total_len = map->total_len;
}
/**
* tso_dma_map_complete - tear down mapping at completion time
* @dev: the device that owns the mapping
* @cstate: state saved by tso_dma_map_completion_save()
*
* Return: true if the IOVA path was used and the mapping has been
* destroyed; false if the fallback per-region path was used and the
* driver must unmap via its normal completion path.
*/
static inline bool
tso_dma_map_complete(struct device *dev,
struct tso_dma_map_completion_state *cstate)
{
if (dma_use_iova(&cstate->iova_state)) {
dma_iova_destroy(dev, &cstate->iova_state, cstate->total_len,
DMA_TO_DEVICE, 0);
return true;
}
return false;
}
#endif /* _TSO_H */