svn commit: r361529 - head/sys/dev/ena
Marcin Wojtas
mw at FreeBSD.org
Tue May 26 16:05:42 UTC 2020
Author: mw
Date: Tue May 26 16:05:42 2020
New Revision: 361529
URL: https://svnweb.freebsd.org/changeset/base/361529
Log:
Refactor ena_tx_map_mbuf() function
There is no guarantee from bus_dmamap_load_mbuf_sg() for matching
mbuf chain segments to dma physical segments.
This patch ensure correctly mapping to LLQ header and DMA segments.
Submitted by: Ido Segev <idose at amazon.com>
Obtained from: Amazon, Inc.
Modified:
head/sys/dev/ena/ena_datapath.c
Modified: head/sys/dev/ena/ena_datapath.c
==============================================================================
--- head/sys/dev/ena/ena_datapath.c Tue May 26 16:02:10 2020 (r361528)
+++ head/sys/dev/ena/ena_datapath.c Tue May 26 16:05:42 2020 (r361529)
@@ -812,9 +812,8 @@ ena_tx_map_mbuf(struct ena_ring *tx_ring, struct ena_t
struct ena_com_buf *ena_buf;
bus_dma_segment_t segs[ENA_BUS_DMA_SEGS];
size_t iseg = 0;
- uint32_t mbuf_head_len, frag_len;
- uint16_t push_len = 0;
- uint16_t delta = 0;
+ uint32_t mbuf_head_len;
+ uint16_t offset;
int rc, nsegs;
mbuf_head_len = mbuf->m_len;
@@ -833,7 +832,6 @@ ena_tx_map_mbuf(struct ena_ring *tx_ring, struct ena_t
goto dma_error;
}
-
if (tx_ring->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) {
/*
* When the device is LLQ mode, the driver will copy
@@ -845,44 +843,48 @@ ena_tx_map_mbuf(struct ena_ring *tx_ring, struct ena_t
* First check if header fits in the mbuf. If not, copy it to
* separate buffer that will be holding linearized data.
*/
- push_len = min_t(uint32_t, mbuf->m_pkthdr.len,
- tx_ring->tx_max_header_size);
- *header_len = push_len;
+ *header_len = min_t(uint32_t, mbuf->m_pkthdr.len, tx_ring->tx_max_header_size);
+
/* If header is in linear space, just point into mbuf's data. */
- if (likely(push_len <= mbuf_head_len)) {
+ if (likely(*header_len <= mbuf_head_len)) {
*push_hdr = mbuf->m_data;
/*
* Otherwise, copy whole portion of header from multiple mbufs
* to intermediate buffer.
*/
} else {
- m_copydata(mbuf, 0, push_len,
- tx_ring->push_buf_intermediate_buf);
+ m_copydata(mbuf, 0, *header_len, tx_ring->push_buf_intermediate_buf);
*push_hdr = tx_ring->push_buf_intermediate_buf;
counter_u64_add(tx_ring->tx_stats.llq_buffer_copy, 1);
- delta = push_len - mbuf_head_len;
}
ena_trace(ENA_DBG | ENA_TXPTH,
"mbuf: %p header_buf->vaddr: %p push_len: %d\n",
- mbuf, *push_hdr, push_len);
+ mbuf, *push_hdr, *header_len);
- /*
- * If header was in linear memory space, map for the dma rest of the data
- * in the first mbuf of the mbuf chain.
- */
- if (mbuf_head_len > push_len) {
- ena_buf->paddr = segs[iseg].ds_addr + push_len;
- ena_buf->len = segs[iseg].ds_len - push_len;
- ena_buf++;
- tx_info->num_of_bufs++;
+ /* If packet is fitted in LLQ header, no need for DMA segments. */
+ if (mbuf->m_pkthdr.len <= tx_ring->tx_max_header_size) {
+ return (0);
+ } else {
+ offset = tx_ring->tx_max_header_size;
+ /*
+ * As Header part is mapped to LLQ header, we can skip it and just
+ * map the residuum of the mbuf to DMA Segments.
+ */
+ while (offset > 0) {
+ if (offset >= segs[iseg].ds_len) {
+ offset -= segs[iseg].ds_len;
+ } else {
+ ena_buf->paddr = segs[iseg].ds_addr + offset;
+ ena_buf->len = segs[iseg].ds_len - offset;
+ ena_buf++;
+ tx_info->num_of_bufs++;
+ offset = 0;
+ }
+ iseg++;
+ }
}
- /*
- * Advance the seg index as either the 1st mbuf was mapped or is
- * a part of push_hdr.
- */
- iseg++;
} else {
*push_hdr = NULL;
/*
@@ -893,41 +895,6 @@ ena_tx_map_mbuf(struct ena_ring *tx_ring, struct ena_t
* header on it's own.
*/
*header_len = 0;
- }
-
- /*
- * If header is in non linear space (delta > 0), then skip mbufs
- * containing header and map the last one containing both header and the
- * packet data.
- * The first segment is already counted in.
- * If LLQ is not supported, the loop will be skipped.
- */
- while (delta > 0) {
- frag_len = segs[iseg].ds_len;
-
- /*
- * If whole segment contains header just move to the
- * next one and reduce delta.
- */
- if (unlikely(delta >= frag_len)) {
- delta -= frag_len;
- } else {
- /*
- * Map rest of the packet data that was contained in
- * the mbuf.
- */
- ena_buf->paddr = segs[iseg].ds_addr + delta;
- ena_buf->len = frag_len - delta;
- ena_buf++;
- tx_info->num_of_bufs++;
-
- delta = 0;
- }
- iseg++;
- }
-
- if (mbuf == NULL) {
- return (0);
}
/* Map rest of the mbuf */
More information about the svn-src-head
mailing list