diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_xsk.c')
| -rw-r--r-- | drivers/net/ethernet/intel/ice/ice_xsk.c | 228 | 
1 files changed, 131 insertions, 97 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c index 056c904b83cc..31565bbafa22 100644 --- a/drivers/net/ethernet/intel/ice/ice_xsk.c +++ b/drivers/net/ethernet/intel/ice/ice_xsk.c @@ -24,13 +24,24 @@ static struct xdp_buff **ice_xdp_buf(struct ice_rx_ring *rx_ring, u32 idx)   */  static void ice_qp_reset_stats(struct ice_vsi *vsi, u16 q_idx)  { -	memset(&vsi->rx_rings[q_idx]->rx_stats, 0, -	       sizeof(vsi->rx_rings[q_idx]->rx_stats)); -	memset(&vsi->tx_rings[q_idx]->stats, 0, -	       sizeof(vsi->tx_rings[q_idx]->stats)); +	struct ice_vsi_stats *vsi_stat; +	struct ice_pf *pf; + +	pf = vsi->back; +	if (!pf->vsi_stats) +		return; + +	vsi_stat = pf->vsi_stats[vsi->idx]; +	if (!vsi_stat) +		return; + +	memset(&vsi_stat->rx_ring_stats[q_idx]->rx_stats, 0, +	       sizeof(vsi_stat->rx_ring_stats[q_idx]->rx_stats)); +	memset(&vsi_stat->tx_ring_stats[q_idx]->stats, 0, +	       sizeof(vsi_stat->tx_ring_stats[q_idx]->stats));  	if (ice_is_xdp_ena_vsi(vsi)) -		memset(&vsi->xdp_rings[q_idx]->stats, 0, -		       sizeof(vsi->xdp_rings[q_idx]->stats)); +		memset(&vsi->xdp_rings[q_idx]->ring_stats->stats, 0, +		       sizeof(vsi->xdp_rings[q_idx]->ring_stats->stats));  }  /** @@ -587,6 +598,112 @@ ice_construct_skb_zc(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp)  }  /** + * ice_clean_xdp_irq_zc - produce AF_XDP descriptors to CQ + * @xdp_ring: XDP Tx ring + */ +static void ice_clean_xdp_irq_zc(struct ice_tx_ring *xdp_ring) +{ +	u16 ntc = xdp_ring->next_to_clean; +	struct ice_tx_desc *tx_desc; +	u16 cnt = xdp_ring->count; +	struct ice_tx_buf *tx_buf; +	u16 completed_frames = 0; +	u16 xsk_frames = 0; +	u16 last_rs; +	int i; + +	last_rs = xdp_ring->next_to_use ? xdp_ring->next_to_use - 1 : cnt - 1; +	tx_desc = ICE_TX_DESC(xdp_ring, last_rs); +	if (tx_desc->cmd_type_offset_bsz & +	    cpu_to_le64(ICE_TX_DESC_DTYPE_DESC_DONE)) { +		if (last_rs >= ntc) +			completed_frames = last_rs - ntc + 1; +		else +			completed_frames = last_rs + cnt - ntc + 1; +	} + +	if (!completed_frames) +		return; + +	if (likely(!xdp_ring->xdp_tx_active)) { +		xsk_frames = completed_frames; +		goto skip; +	} + +	ntc = xdp_ring->next_to_clean; +	for (i = 0; i < completed_frames; i++) { +		tx_buf = &xdp_ring->tx_buf[ntc]; + +		if (tx_buf->type == ICE_TX_BUF_XSK_TX) { +			tx_buf->type = ICE_TX_BUF_EMPTY; +			xsk_buff_free(tx_buf->xdp); +			xdp_ring->xdp_tx_active--; +		} else { +			xsk_frames++; +		} + +		ntc++; +		if (ntc >= xdp_ring->count) +			ntc = 0; +	} +skip: +	tx_desc->cmd_type_offset_bsz = 0; +	xdp_ring->next_to_clean += completed_frames; +	if (xdp_ring->next_to_clean >= cnt) +		xdp_ring->next_to_clean -= cnt; +	if (xsk_frames) +		xsk_tx_completed(xdp_ring->xsk_pool, xsk_frames); +} + +/** + * ice_xmit_xdp_tx_zc - AF_XDP ZC handler for XDP_TX + * @xdp: XDP buffer to xmit + * @xdp_ring: XDP ring to produce descriptor onto + * + * note that this function works directly on xdp_buff, no need to convert + * it to xdp_frame. xdp_buff pointer is stored to ice_tx_buf so that cleaning + * side will be able to xsk_buff_free() it. + * + * Returns ICE_XDP_TX for successfully produced desc, ICE_XDP_CONSUMED if there + * was not enough space on XDP ring + */ +static int ice_xmit_xdp_tx_zc(struct xdp_buff *xdp, +			      struct ice_tx_ring *xdp_ring) +{ +	u32 size = xdp->data_end - xdp->data; +	u32 ntu = xdp_ring->next_to_use; +	struct ice_tx_desc *tx_desc; +	struct ice_tx_buf *tx_buf; +	dma_addr_t dma; + +	if (ICE_DESC_UNUSED(xdp_ring) < ICE_RING_QUARTER(xdp_ring)) { +		ice_clean_xdp_irq_zc(xdp_ring); +		if (!ICE_DESC_UNUSED(xdp_ring)) { +			xdp_ring->ring_stats->tx_stats.tx_busy++; +			return ICE_XDP_CONSUMED; +		} +	} + +	dma = xsk_buff_xdp_get_dma(xdp); +	xsk_buff_raw_dma_sync_for_device(xdp_ring->xsk_pool, dma, size); + +	tx_buf = &xdp_ring->tx_buf[ntu]; +	tx_buf->xdp = xdp; +	tx_buf->type = ICE_TX_BUF_XSK_TX; +	tx_desc = ICE_TX_DESC(xdp_ring, ntu); +	tx_desc->buf_addr = cpu_to_le64(dma); +	tx_desc->cmd_type_offset_bsz = ice_build_ctob(ICE_TX_DESC_CMD_EOP, +						      0, size, 0); +	xdp_ring->xdp_tx_active++; + +	if (++ntu == xdp_ring->count) +		ntu = 0; +	xdp_ring->next_to_use = ntu; + +	return ICE_XDP_TX; +} + +/**   * ice_run_xdp_zc - Executes an XDP program in zero-copy path   * @rx_ring: Rx ring   * @xdp: xdp_buff used as input to the XDP program @@ -619,7 +736,7 @@ ice_run_xdp_zc(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,  	case XDP_PASS:  		break;  	case XDP_TX: -		result = ice_xmit_xdp_buff(xdp, xdp_ring); +		result = ice_xmit_xdp_tx_zc(xdp, xdp_ring);  		if (result == ICE_XDP_CONSUMED)  			goto out_failure;  		break; @@ -722,7 +839,7 @@ construct_skb:  		/* XDP_PASS path */  		skb = ice_construct_skb_zc(rx_ring, xdp);  		if (!skb) { -			rx_ring->rx_stats.alloc_buf_failed++; +			rx_ring->ring_stats->rx_stats.alloc_buf_failed++;  			break;  		} @@ -749,7 +866,7 @@ construct_skb:  	if (entries_to_alloc > ICE_RING_QUARTER(rx_ring))  		failure |= !ice_alloc_rx_bufs_zc(rx_ring, entries_to_alloc); -	ice_finalize_xdp_rx(xdp_ring, xdp_xmit); +	ice_finalize_xdp_rx(xdp_ring, xdp_xmit, 0);  	ice_update_rx_ring_stats(rx_ring, total_rx_packets, total_rx_bytes);  	if (xsk_uses_need_wakeup(rx_ring->xsk_pool)) { @@ -765,75 +882,6 @@ construct_skb:  }  /** - * ice_clean_xdp_tx_buf - Free and unmap XDP Tx buffer - * @xdp_ring: XDP Tx ring - * @tx_buf: Tx buffer to clean - */ -static void -ice_clean_xdp_tx_buf(struct ice_tx_ring *xdp_ring, struct ice_tx_buf *tx_buf) -{ -	xdp_return_frame((struct xdp_frame *)tx_buf->raw_buf); -	xdp_ring->xdp_tx_active--; -	dma_unmap_single(xdp_ring->dev, dma_unmap_addr(tx_buf, dma), -			 dma_unmap_len(tx_buf, len), DMA_TO_DEVICE); -	dma_unmap_len_set(tx_buf, len, 0); -} - -/** - * ice_clean_xdp_irq_zc - produce AF_XDP descriptors to CQ - * @xdp_ring: XDP Tx ring - */ -static void ice_clean_xdp_irq_zc(struct ice_tx_ring *xdp_ring) -{ -	u16 ntc = xdp_ring->next_to_clean; -	struct ice_tx_desc *tx_desc; -	u16 cnt = xdp_ring->count; -	struct ice_tx_buf *tx_buf; -	u16 xsk_frames = 0; -	u16 last_rs; -	int i; - -	last_rs = xdp_ring->next_to_use ? xdp_ring->next_to_use - 1 : cnt - 1; -	tx_desc = ICE_TX_DESC(xdp_ring, last_rs); -	if ((tx_desc->cmd_type_offset_bsz & -	    cpu_to_le64(ICE_TX_DESC_DTYPE_DESC_DONE))) { -		if (last_rs >= ntc) -			xsk_frames = last_rs - ntc + 1; -		else -			xsk_frames = last_rs + cnt - ntc + 1; -	} - -	if (!xsk_frames) -		return; - -	if (likely(!xdp_ring->xdp_tx_active)) -		goto skip; - -	ntc = xdp_ring->next_to_clean; -	for (i = 0; i < xsk_frames; i++) { -		tx_buf = &xdp_ring->tx_buf[ntc]; - -		if (tx_buf->raw_buf) { -			ice_clean_xdp_tx_buf(xdp_ring, tx_buf); -			tx_buf->raw_buf = NULL; -		} else { -			xsk_frames++; -		} - -		ntc++; -		if (ntc >= xdp_ring->count) -			ntc = 0; -	} -skip: -	tx_desc->cmd_type_offset_bsz = 0; -	xdp_ring->next_to_clean += xsk_frames; -	if (xdp_ring->next_to_clean >= cnt) -		xdp_ring->next_to_clean -= cnt; -	if (xsk_frames) -		xsk_tx_completed(xdp_ring->xsk_pool, xsk_frames); -} - -/**   * ice_xmit_pkt - produce a single HW Tx descriptor out of AF_XDP descriptor   * @xdp_ring: XDP ring to produce the HW Tx descriptor on   * @desc: AF_XDP descriptor to pull the DMA address and length from @@ -907,20 +955,6 @@ static void ice_fill_tx_hw_ring(struct ice_tx_ring *xdp_ring, struct xdp_desc *d  }  /** - * ice_set_rs_bit - set RS bit on last produced descriptor (one behind current NTU) - * @xdp_ring: XDP ring to produce the HW Tx descriptors on - */ -static void ice_set_rs_bit(struct ice_tx_ring *xdp_ring) -{ -	u16 ntu = xdp_ring->next_to_use ? xdp_ring->next_to_use - 1 : xdp_ring->count - 1; -	struct ice_tx_desc *tx_desc; - -	tx_desc = ICE_TX_DESC(xdp_ring, ntu); -	tx_desc->cmd_type_offset_bsz |= -		cpu_to_le64(ICE_TX_DESC_CMD_RS << ICE_TXD_QW1_CMD_S); -} - -/**   * ice_xmit_zc - take entries from XSK Tx ring and place them onto HW Tx ring   * @xdp_ring: XDP ring to produce the HW Tx descriptors on   * @@ -1054,12 +1088,12 @@ void ice_xsk_clean_xdp_ring(struct ice_tx_ring *xdp_ring)  	while (ntc != ntu) {  		struct ice_tx_buf *tx_buf = &xdp_ring->tx_buf[ntc]; -		if (tx_buf->raw_buf) -			ice_clean_xdp_tx_buf(xdp_ring, tx_buf); -		else +		if (tx_buf->type == ICE_TX_BUF_XSK_TX) { +			tx_buf->type = ICE_TX_BUF_EMPTY; +			xsk_buff_free(tx_buf->xdp); +		} else {  			xsk_frames++; - -		tx_buf->raw_buf = NULL; +		}  		ntc++;  		if (ntc >= xdp_ring->count)  |