* write_sgl - populate a scatter/gather list for a packet * @mbuf: the packet * @q: the Tx queue we are writing into * @sgl: starting location for writing the SGL * @end: points right after the end of the SGL * @start: start offset into mbuf main-body data to include in the SGL * @addr: address of mapped region * * Generates a scatter/gather list for the buffers that make up a packet. * T
| 544 | * wrap around, i.e., @end > @sgl. |
| 545 | */ |
| 546 | static void write_sgl(struct rte_mbuf *mbuf, struct sge_txq *q, |
| 547 | struct ulptx_sgl *sgl, u64 *end, unsigned int start, |
| 548 | const dma_addr_t *addr) |
| 549 | { |
| 550 | unsigned int i, len; |
| 551 | struct ulptx_sge_pair *to; |
| 552 | struct rte_mbuf *m = mbuf; |
| 553 | unsigned int nfrags = m->nb_segs; |
| 554 | struct ulptx_sge_pair buf[nfrags / 2]; |
| 555 | |
| 556 | len = m->data_len - start; |
| 557 | sgl->len0 = htonl(len); |
| 558 | sgl->addr0 = rte_cpu_to_be_64(addr[0]); |
| 559 | |
| 560 | sgl->cmd_nsge = htonl(V_ULPTX_CMD(ULP_TX_SC_DSGL) | |
| 561 | V_ULPTX_NSGE(nfrags)); |
| 562 | if (likely(--nfrags == 0)) |
| 563 | return; |
| 564 | /* |
| 565 | * Most of the complexity below deals with the possibility we hit the |
| 566 | * end of the queue in the middle of writing the SGL. For this case |
| 567 | * only we create the SGL in a temporary buffer and then copy it. |
| 568 | */ |
| 569 | to = (u8 *)end > (u8 *)q->stat ? buf : sgl->sge; |
| 570 | |
| 571 | for (i = 0; nfrags >= 2; nfrags -= 2, to++) { |
| 572 | m = m->next; |
| 573 | to->len[0] = rte_cpu_to_be_32(m->data_len); |
| 574 | to->addr[0] = rte_cpu_to_be_64(addr[++i]); |
| 575 | m = m->next; |
| 576 | to->len[1] = rte_cpu_to_be_32(m->data_len); |
| 577 | to->addr[1] = rte_cpu_to_be_64(addr[++i]); |
| 578 | } |
| 579 | if (nfrags) { |
| 580 | m = m->next; |
| 581 | to->len[0] = rte_cpu_to_be_32(m->data_len); |
| 582 | to->len[1] = rte_cpu_to_be_32(0); |
| 583 | to->addr[0] = rte_cpu_to_be_64(addr[i + 1]); |
| 584 | } |
| 585 | if (unlikely((u8 *)end > (u8 *)q->stat)) { |
| 586 | unsigned int part0 = RTE_PTR_DIFF((u8 *)q->stat, |
| 587 | (u8 *)sgl->sge); |
| 588 | unsigned int part1; |
| 589 | |
| 590 | if (likely(part0)) |
| 591 | memcpy(sgl->sge, buf, part0); |
| 592 | part1 = RTE_PTR_DIFF((u8 *)end, (u8 *)q->stat); |
| 593 | rte_memcpy(q->desc, RTE_PTR_ADD((u8 *)buf, part0), part1); |
| 594 | end = RTE_PTR_ADD((void *)q->desc, part1); |
| 595 | } |
| 596 | if ((uintptr_t)end & 8) /* 0-pad to multiple of 16 */ |
| 597 | *(u64 *)end = 0; |
| 598 | } |
| 599 | |
| 600 | #define IDXDIFF(head, tail, wrap) \ |
| 601 | ((head) >= (tail) ? (head) - (tail) : (wrap) - (tail) + (head)) |
no test coverage detected