Introduce xdp tx mb support for i40e and ixgbe
Subsystems (3)
cover Introduce xdp tx mb support for i40e and ixgbe
Add the capability to map non-linear xdp frames in ndo_xdp_xmit and XDP_TX for i40e and ixgbe drivers.
Lorenzo Bianconi (2):
ixgbe: add xdp frags support to ndo_xdp_xmit
i40e: add xdp frags support to ndo_xdp_xmit
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 86 +++++++++++----- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 99 ++++++++++++------- 2 files changed, 124 insertions(+), 61 deletions(-)
Signature · 1 line
2.35.1
RFC 1/2 ixgbe: add xdp frags support to ndo_xdp_xmit
Add the capability to map non-linear xdp frames in XDP_TX and ndo_xdp_xmit callback.
Signed-off-by Lorenzo Bianconi <[email protected]>
--- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 99 ++++++++++++------- 1 file changed, 63 insertions(+), 36 deletions(-)
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +63 -36
@@ -8571,57 +8571,84 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,int ixgbe_xmit_xdp_ring (struct ixgbe_ring *ring,struct xdp_frame *xdpf) { -struct ixgbe_tx_buffer *tx_buffer; -union ixgbe_adv_tx_desc *tx_desc; -u32 len, cmd_type; -dma_addr_t dma; -u16 i; +struct skb_shared_info *sinfo =xdp_get_shared_info_from_frame (xdpf); +u8 nr_frags =unlikely (xdp_frame_has_frags (xdpf)) ? sinfo->nr_frags :0 ; +u16 i =0 , index = ring->next_to_use; +struct ixgbe_tx_buffer *tx_head = &ring->tx_buffer_info[index]; +struct ixgbe_tx_buffer *tx_buff = tx_head; +union ixgbe_adv_tx_desc *tx_desc =IXGBE_TX_DESC (ring, index); +u32 cmd_type, len = xdpf->len; +void *data = xdpf->data; + +if (unlikely (ixgbe_desc_unused (ring) <1 + nr_frags)) +return IXGBE_XDP_CONSUMED ; - len = xdpf->len; + tx_head->bytecount =xdp_get_frame_len (xdpf); + tx_head->gso_segs =1 ; + tx_head->xdpf = xdpf; -if (unlikely (!ixgbe_desc_unused (ring))) -return IXGBE_XDP_CONSUMED ; + tx_desc->read.olinfo_status = +cpu_to_le32 (tx_head->bytecount <<IXGBE_ADVTXD_PAYLEN_SHIFT ); - dma =dma_map_single (ring->dev, xdpf->data, len,DMA_TO_DEVICE ); -if (dma_mapping_error (ring->dev, dma)) -return IXGBE_XDP_CONSUMED ; +for (;;) { +dma_addr_t dma; -/* record the location of the first descriptor for this packet */ - tx_buffer = &ring->tx_buffer_info[ring->next_to_use]; - tx_buffer->bytecount = len; - tx_buffer->gso_segs =1 ; - tx_buffer->protocol =0 ; + dma =dma_map_single (ring->dev, data, len,DMA_TO_DEVICE ); +if (dma_mapping_error (ring->dev, dma)) + goto unmap; + +dma_unmap_len_set (tx_buff, len, len); +dma_unmap_addr_set (tx_buff, dma, dma); - i = ring->next_to_use; - tx_desc =IXGBE_TX_DESC (ring, i); + cmd_type =IXGBE_ADVTXD_DTYP_DATA |IXGBE_ADVTXD_DCMD_DEXT | +IXGBE_ADVTXD_DCMD_IFCS | len; + tx_desc->read.cmd_type_len =cpu_to_le32 (cmd_type); + tx_desc->read.buffer_addr =cpu_to_le64 (dma); + tx_buff->protocol =0 ; -dma_unmap_len_set (tx_buffer, len, len); -dma_unmap_addr_set (tx_buffer, dma, dma); - tx_buffer->xdpf = xdpf; +if (++index == ring->count) + index =0 ; - tx_desc->read.buffer_addr =cpu_to_le64 (dma); +if (i == nr_frags) +break ; + + tx_buff = &ring->tx_buffer_info[index]; + tx_desc =IXGBE_TX_DESC (ring, index); + + tx_desc->read.olinfo_status =0 ; + data =skb_frag_address (&sinfo->frags[i]); + len =skb_frag_size (&sinfo->frags[i]); + i++; + }/* put descriptor type bits */ - cmd_type =IXGBE_ADVTXD_DTYP_DATA | -IXGBE_ADVTXD_DCMD_DEXT | -IXGBE_ADVTXD_DCMD_IFCS ; - cmd_type |= len |IXGBE_TXD_CMD ; - tx_desc->read.cmd_type_len =cpu_to_le32 (cmd_type); - tx_desc->read.olinfo_status = -cpu_to_le32 (len <<IXGBE_ADVTXD_PAYLEN_SHIFT ); + tx_desc->read.cmd_type_len |=cpu_to_le32 (IXGBE_TXD_CMD );/* Avoid any potential race with xdp_xmit and cleanup */ smp_wmb (); -/* set next_to_watch value indicating a packet is present */ - i++; -if (i == ring->count) - i =0 ; - - tx_buffer->next_to_watch = tx_desc; - ring->next_to_use = i; + tx_head->next_to_watch = tx_desc; + ring->next_to_use = index;return IXGBE_XDP_TX ; + +unmap: +for (;;) { + tx_buff = &ring->tx_buffer_info[index]; +if (dma_unmap_len (tx_buff, len)) +dma_unmap_page (ring->dev,dma_unmap_addr (tx_buff, dma), +dma_unmap_len (tx_buff, len), +DMA_TO_DEVICE ); +dma_unmap_len_set (tx_buff, len,0 ); +if (tx_buff == tx_head) +break ; + +if (!index) + index += ring->count; + index--; + } + +return IXGBE_XDP_CONSUMED ; } netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
Signature · 1 line
2.35.1
RFC 2/2 i40e: add xdp frags support to ndo_xdp_xmit
In reply to Lorenzo BianconiAdd the capability to map non-linear xdp frames in XDP_TX and ndo_xdp_xmit callback.
Signed-off-by Lorenzo Bianconi <[email protected]>
--- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 86 +++++++++++++++------ 1 file changed, 61 insertions(+), 25 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_txrx.c +61 -25
@@ -3688,35 +3688,55 @@ u16 i40e_lan_select_queue(struct net_device *netdev,static int i40e_xmit_xdp_ring (struct xdp_frame *xdpf,struct i40e_ring *xdp_ring) { -u16 i = xdp_ring->next_to_use; -struct i40e_tx_buffer *tx_bi; -struct i40e_tx_desc *tx_desc; +struct skb_shared_info *sinfo =xdp_get_shared_info_from_frame (xdpf); +u8 nr_frags =unlikely (xdp_frame_has_frags (xdpf)) ? sinfo->nr_frags :0 ; +u16 i =0 , index = xdp_ring->next_to_use; +struct i40e_tx_buffer *tx_head = &xdp_ring->tx_bi[index]; +struct i40e_tx_buffer *tx_bi = tx_head; +struct i40e_tx_desc *tx_desc =I40E_TX_DESC (xdp_ring, index);void *data = xdpf->data;u32 size = xdpf->len; -dma_addr_t dma; -if (!unlikely (I40E_DESC_UNUSED (xdp_ring))) { +if (unlikely (I40E_DESC_UNUSED (xdp_ring) <1 + nr_frags)) { xdp_ring->tx_stats.tx_busy++;return I40E_XDP_CONSUMED ; } - dma =dma_map_single (xdp_ring->dev, data, size,DMA_TO_DEVICE ); -if (dma_mapping_error (xdp_ring->dev, dma)) -return I40E_XDP_CONSUMED ; - tx_bi = &xdp_ring->tx_bi[i]; - tx_bi->bytecount = size; - tx_bi->gso_segs =1 ; - tx_bi->xdpf = xdpf; + tx_head->bytecount =xdp_get_frame_len (xdpf); + tx_head->gso_segs =1 ; + tx_head->xdpf = xdpf; -/* record length, and DMA address */ -dma_unmap_len_set (tx_bi, len, size); -dma_unmap_addr_set (tx_bi, dma, dma); +for (;;) { +dma_addr_t dma; - tx_desc =I40E_TX_DESC (xdp_ring, i); - tx_desc->buffer_addr =cpu_to_le64 (dma); - tx_desc->cmd_type_offset_bsz =build_ctob (I40E_TX_DESC_CMD_ICRC - |I40E_TXD_CMD , -0 , size,0 ); + dma =dma_map_single (xdp_ring->dev, data, size,DMA_TO_DEVICE ); +if (dma_mapping_error (xdp_ring->dev, dma)) + goto unmap; + +/* record length, and DMA address */ +dma_unmap_len_set (tx_bi, len, size); +dma_unmap_addr_set (tx_bi, dma, dma); + + tx_desc->buffer_addr =cpu_to_le64 (dma); + tx_desc->cmd_type_offset_bsz = +build_ctob (I40E_TX_DESC_CMD_ICRC ,0 , size,0 ); + +if (++index == xdp_ring->count) + index =0 ; + +if (i == nr_frags) +break ; + + tx_bi = &xdp_ring->tx_bi[index]; + tx_desc =I40E_TX_DESC (xdp_ring, index); + + data =skb_frag_address (&sinfo->frags[i]); + size =skb_frag_size (&sinfo->frags[i]); + i++; + } + + tx_desc->cmd_type_offset_bsz |= +cpu_to_le64 (I40E_TXD_CMD <<I40E_TXD_QW1_CMD_SHIFT );/* Make certain all of the status bits have been updated * before next_to_watch is written.
@@ -3724,14 +3744,30 @@ static int i40e_xmit_xdp_ring(struct xdp_frame *xdpf,smp_wmb (); xdp_ring->xdp_tx_active++; - i++; -if (i == xdp_ring->count) - i =0 ; - tx_bi->next_to_watch = tx_desc; - xdp_ring->next_to_use = i; + tx_head->next_to_watch = tx_desc; + xdp_ring->next_to_use = index;return I40E_XDP_TX ; + +unmap: +for (;;) { + tx_bi = &xdp_ring->tx_bi[index]; +if (dma_unmap_len (tx_bi, len)) +dma_unmap_page (xdp_ring->dev, +dma_unmap_addr (tx_bi, dma), +dma_unmap_len (tx_bi, len), +DMA_TO_DEVICE ); +dma_unmap_len_set (tx_bi, len,0 ); +if (tx_bi == tx_head) +break ; + +if (!index) + index += xdp_ring->count; + index--; + } + +return I40E_XDP_CONSUMED ; }/**
Signature · 1 line
2.35.1