Skip to content

Commit 395ae75

Browse files
committed
ixgbevf: Add pseudo header split
This patch introduces pseudo header split support in the ixgbevf driver, specifically targeting ixgbe_mac_82599_vf. On older hardware (e.g. ixgbe_mac_82599_vf), RX DMA write size can only be limited in 1K increments. This causes issues when attempting to fit multiple packets per page, as a DMA write may overwrite the headroom of the next packet. To address this, introduce pseudo header split support, where the hardware copies the full L2 header into a dedicated header buffer. This avoids the need for HR/TR alignment and allows safe skb construction from the header buffer without risking overwrites. Signed-off-by: Natalia Wochtman <natalia.wochtman@intel.com>
1 parent 241e4fc commit 395ae75

2 files changed

Lines changed: 143 additions & 15 deletions

File tree

drivers/net/ethernet/intel/ixgbevf/ixgbevf.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ struct ixgbevf_ring {
8989
dma_addr_t dma; /* phys. address of descriptor ring */
9090
unsigned int size; /* length in bytes */
9191
u32 truesize; /* Rx buffer full size */
92+
u32 hdr_truesize; /* Rx header buffer full size */
9293
u16 count; /* amount of descriptors */
9394
u16 next_to_use;
9495
u16 next_to_clean;
@@ -104,7 +105,12 @@ struct ixgbevf_ring {
104105
struct ixgbevf_tx_queue_stats tx_stats;
105106
struct ixgbevf_rx_queue_stats rx_stats;
106107
};
108+
109+
struct libeth_fqe *hdr_fqes;
110+
struct page_pool *hdr_pp;
111+
107112
struct xdp_rxq_info xdp_rxq;
113+
108114
u64 hw_csum_rx_error;
109115
u8 __iomem *tail;
110116

@@ -113,6 +119,7 @@ struct ixgbevf_ring {
113119
*/
114120
u16 reg_idx;
115121
int queue_index; /* needed for multiqueue queue management */
122+
u32 hdr_buf_len;
116123
u32 rx_buf_len;
117124
struct libeth_xdp_buff_stash xdp_stash;
118125
} ____cacheline_internodealigned_in_smp;
@@ -147,6 +154,8 @@ struct ixgbevf_ring {
147154
#define IXGBEVF_RX_PAGE_LEN(hr) (ALIGN_DOWN(LIBETH_RX_PAGE_LEN(hr), \
148155
IXGBE_SRRCTL_BSIZEPKT_STEP))
149156

157+
#define IXGBEVF_FLAG_HSPLIT BIT(0)
158+
150159
#define IXGBE_TX_FLAGS_CSUM BIT(0)
151160
#define IXGBE_TX_FLAGS_VLAN BIT(1)
152161
#define IXGBE_TX_FLAGS_TSO BIT(2)

drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c

Lines changed: 134 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,12 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_ring *rx_ring,
568568
.truesize = rx_ring->truesize,
569569
.count = rx_ring->count,
570570
};
571+
const struct libeth_fq_fp hdr_fq = {
572+
.pp = rx_ring->hdr_pp,
573+
.fqes = rx_ring->hdr_fqes,
574+
.truesize = rx_ring->hdr_truesize,
575+
.count = rx_ring->count,
576+
};
571577
u16 ntu = rx_ring->next_to_use;
572578

573579
/* nothing to do or no valid netdev defined */
@@ -584,6 +590,14 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_ring *rx_ring,
584590

585591
rx_desc->read.pkt_addr = cpu_to_le64(addr);
586592

593+
if (!hdr_fq.pp)
594+
goto next;
595+
596+
addr = libeth_rx_alloc(&hdr_fq, ntu);
597+
if (addr == DMA_MAPPING_ERROR)
598+
return;
599+
600+
next:
587601
rx_desc++;
588602
ntu++;
589603
if (unlikely(ntu == fq.count)) {
@@ -781,6 +795,32 @@ static int ixgbevf_run_xdp(struct ixgbevf_adapter *adapter,
781795
return result;
782796
}
783797

798+
static u32 ixgbevf_rx_hsplit_wa(const struct libeth_fqe *hdr,
799+
struct libeth_fqe *buf, u32 data_len)
800+
{
801+
u32 copy = data_len <= L1_CACHE_BYTES ? data_len : ETH_HLEN;
802+
struct page *hdr_page, *buf_page;
803+
const void *src;
804+
void *dst;
805+
806+
if (unlikely(netmem_is_net_iov(buf->netmem)) ||
807+
!libeth_rx_sync_for_cpu(buf, copy))
808+
return 0;
809+
810+
hdr_page = __netmem_to_page(hdr->netmem);
811+
buf_page = __netmem_to_page(buf->netmem);
812+
813+
dst = page_address(hdr_page) + hdr->offset +
814+
pp_page_to_nmdesc(hdr_page)->pp->p.offset;
815+
src = page_address(buf_page) + buf->offset +
816+
pp_page_to_nmdesc(buf_page)->pp->p.offset;
817+
818+
memcpy(dst, src, LARGEST_ALIGN(copy));
819+
buf->offset += copy;
820+
821+
return copy;
822+
}
823+
784824
static int ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
785825
struct ixgbevf_ring *rx_ring,
786826
int budget)
@@ -798,6 +838,8 @@ static int ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
798838
while (likely(total_rx_packets < budget)) {
799839
union ixgbe_adv_rx_desc *rx_desc;
800840
struct libeth_fqe *rx_buffer;
841+
struct libeth_fqe *hdr_buff;
842+
unsigned int hdr_size = 0;
801843
unsigned int size;
802844

803845
/* return some buffers to hardware, one at a time is too slow */
@@ -818,6 +860,20 @@ static int ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
818860
rmb();
819861

820862
rx_buffer = &rx_ring->rx_fqes[rx_ring->next_to_clean];
863+
864+
if (unlikely(rx_ring->hdr_pp)) {
865+
hdr_buff = &rx_ring->hdr_fqes[rx_ring->next_to_clean];
866+
867+
if (!xdp->data) {
868+
hdr_size = ixgbevf_rx_hsplit_wa(hdr_buff,
869+
rx_buffer,
870+
size);
871+
size -= hdr_size ? : size;
872+
}
873+
874+
libeth_xdp_process_buff(xdp, hdr_buff, hdr_size);
875+
}
876+
821877
libeth_xdp_process_buff(xdp, rx_buffer, size);
822878

823879
cleaned_count++;
@@ -3054,19 +3110,38 @@ static int ixgbevf_setup_all_tx_resources(struct ixgbevf_adapter *adapter)
30543110
return err;
30553111
}
30563112

3057-
/**
3058-
* ixgbevf_setup_rx_resources - allocate Rx resources (Descriptors)
3059-
* @adapter: board private structure
3060-
* @rx_ring: Rx descriptor ring (for a specific queue) to setup
3061-
*
3062-
* Returns 0 on success, negative on failure
3063-
**/
3064-
int ixgbevf_setup_rx_resources(struct ixgbevf_adapter *adapter,
3065-
struct ixgbevf_ring *rx_ring)
3113+
static void ixgbvf_rx_destroy_pp(struct ixgbevf_ring *rx_ring)
3114+
{
3115+
struct libeth_fq fq = {
3116+
.pp = rx_ring->pp,
3117+
.fqes = rx_ring->rx_fqes,
3118+
};
3119+
3120+
libeth_rx_fq_destroy(&fq);
3121+
rx_ring->rx_fqes = NULL;
3122+
rx_ring->pp = NULL;
3123+
3124+
if (!rx_ring->hdr_pp)
3125+
return;
3126+
3127+
fq = (struct libeth_fq) {
3128+
.pp = rx_ring->hdr_pp,
3129+
.fqes = rx_ring->hdr_fqes,
3130+
};
3131+
3132+
libeth_rx_fq_destroy(&fq);
3133+
rx_ring->hdr_fqes = NULL;
3134+
rx_ring->hdr_pp = NULL;
3135+
}
3136+
3137+
static int ixgbvf_rx_create_pp(struct ixgbevf_ring *rx_ring)
30663138
{
3139+
u32 adapter_flags = rx_ring->q_vector->adapter->flags;
3140+
30673141
struct libeth_fq fq = {
30683142
.count = rx_ring->count,
30693143
.nid = NUMA_NO_NODE,
3144+
.hsplit = adapter_flags & IXGBEVF_FLAG_HSPLIT,
30703145
.type = LIBETH_FQE_MTU,
30713146
.xdp = !!rx_ring->xdp_prog,
30723147
.buf_len = IXGBEVF_RX_PAGE_LEN(rx_ring->xdp_prog ?
@@ -3084,34 +3159,75 @@ int ixgbevf_setup_rx_resources(struct ixgbevf_adapter *adapter,
30843159
rx_ring->truesize = fq.truesize;
30853160
rx_ring->rx_buf_len = fq.buf_len;
30863161

3162+
if (!fq.hsplit)
3163+
return 0;
3164+
3165+
fq = (struct libeth_fq) {
3166+
.count = rx_ring->count,
3167+
.nid = NUMA_NO_NODE,
3168+
.type = LIBETH_FQE_HDR,
3169+
.xdp = !!rx_ring->xdp_prog,
3170+
};
3171+
3172+
ret = libeth_rx_fq_create(&fq, &rx_ring->q_vector->napi);
3173+
if (ret)
3174+
goto err;
3175+
3176+
rx_ring->hdr_pp = fq.pp;
3177+
rx_ring->hdr_fqes = fq.fqes;
3178+
rx_ring->hdr_truesize = fq.truesize;
3179+
rx_ring->hdr_buf_len = fq.buf_len;
3180+
3181+
return 0;
3182+
3183+
err:
3184+
ixgbvf_rx_destroy_pp(rx_ring);
3185+
return ret;
3186+
}
3187+
3188+
/**
3189+
* ixgbevf_setup_rx_resources - allocate Rx resources
3190+
* @adapter: board private structure
3191+
* @rx_ring: Rx descriptor ring (for a specific queue) to setup
3192+
*
3193+
* Returns: 0 on success, negative on failure.
3194+
**/
3195+
int ixgbevf_setup_rx_resources(struct ixgbevf_adapter *adapter,
3196+
struct ixgbevf_ring *rx_ring)
3197+
{
3198+
int ret;
3199+
3200+
ret = ixgbvf_rx_create_pp(rx_ring);
3201+
if (ret)
3202+
return ret;
3203+
30873204
u64_stats_init(&rx_ring->syncp);
30883205

30893206
/* Round up to nearest 4K */
30903207
rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc);
30913208
rx_ring->size = ALIGN(rx_ring->size, 4096);
30923209

3093-
rx_ring->desc = dma_alloc_coherent(fq.pp->p.dev, rx_ring->size,
3210+
rx_ring->desc = dma_alloc_coherent(rx_ring->pp->p.dev, rx_ring->size,
30943211
&rx_ring->dma, GFP_KERNEL);
30953212

30963213
if (!rx_ring->desc)
30973214
goto err;
30983215

30993216
/* XDP RX-queue info */
31003217
ret = __xdp_rxq_info_reg(&rx_ring->xdp_rxq, adapter->netdev,
3101-
rx_ring->queue_index, 0, fq.buf_len);
3218+
rx_ring->queue_index, 0, rx_ring->rx_buf_len);
31023219
if (ret)
31033220
goto err;
31043221

3105-
xdp_rxq_info_attach_page_pool(&rx_ring->xdp_rxq, fq.pp);
3222+
xdp_rxq_info_attach_page_pool(&rx_ring->xdp_rxq, rx_ring->pp);
31063223

31073224
rx_ring->xdp_prog = adapter->xdp_prog;
31083225

31093226
return 0;
31103227
err:
3111-
libeth_rx_fq_destroy(&fq);
3112-
rx_ring->rx_fqes = NULL;
3113-
rx_ring->pp = NULL;
3228+
ixgbvf_rx_destroy_pp(rx_ring);
31143229
dev_err(rx_ring->dev, "Unable to allocate memory for the Rx descriptor ring\n");
3230+
31153231
return ret;
31163232
}
31173233

@@ -4222,6 +4338,9 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
42224338
netdev->priv_flags |= IFF_UNICAST_FLT;
42234339
netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_RX_SG;
42244340

4341+
if (adapter->hw.mac.type == ixgbe_mac_82599_vf)
4342+
adapter->flags |= IXGBEVF_FLAG_HSPLIT;
4343+
42254344
/* MTU range: 68 - 1504 or 9710 */
42264345
netdev->min_mtu = ETH_MIN_MTU;
42274346
switch (adapter->hw.api_version) {

0 commit comments

Comments
 (0)