| 602 | } |
| 603 | |
| 604 | static int |
| 605 | awg_encap(struct awg_softc *sc, struct mbuf **mp) |
| 606 | { |
| 607 | bus_dmamap_t map; |
| 608 | bus_dma_segment_t segs[TX_MAX_SEGS]; |
| 609 | int error, nsegs, cur, first, last, i; |
| 610 | u_int csum_flags; |
| 611 | uint32_t flags, status; |
| 612 | struct mbuf *m; |
| 613 | |
| 614 | cur = first = sc->tx.cur; |
| 615 | map = sc->tx.buf_map[first].map; |
| 616 | |
| 617 | m = *mp; |
| 618 | error = bus_dmamap_load_mbuf_sg(sc->tx.buf_tag, map, m, segs, |
| 619 | &nsegs, BUS_DMA_NOWAIT); |
| 620 | if (error == EFBIG) { |
| 621 | m = m_collapse(m, M_NOWAIT, TX_MAX_SEGS); |
| 622 | if (m == NULL) { |
| 623 | device_printf(sc->dev, "awg_encap: m_collapse failed\n"); |
| 624 | m_freem(*mp); |
| 625 | *mp = NULL; |
| 626 | return (ENOMEM); |
| 627 | } |
| 628 | *mp = m; |
| 629 | error = bus_dmamap_load_mbuf_sg(sc->tx.buf_tag, map, m, |
| 630 | segs, &nsegs, BUS_DMA_NOWAIT); |
| 631 | if (error != 0) { |
| 632 | m_freem(*mp); |
| 633 | *mp = NULL; |
| 634 | } |
| 635 | } |
| 636 | if (error != 0) { |
| 637 | device_printf(sc->dev, "awg_encap: bus_dmamap_load_mbuf_sg failed\n"); |
| 638 | return (error); |
| 639 | } |
| 640 | if (nsegs == 0) { |
| 641 | m_freem(*mp); |
| 642 | *mp = NULL; |
| 643 | return (EIO); |
| 644 | } |
| 645 | |
| 646 | if (sc->tx.queued + nsegs > TX_DESC_COUNT) { |
| 647 | bus_dmamap_unload(sc->tx.buf_tag, map); |
| 648 | return (ENOBUFS); |
| 649 | } |
| 650 | |
| 651 | bus_dmamap_sync(sc->tx.buf_tag, map, BUS_DMASYNC_PREWRITE); |
| 652 | |
| 653 | flags = TX_FIR_DESC; |
| 654 | status = 0; |
| 655 | if ((m->m_pkthdr.csum_flags & CSUM_IP) != 0) { |
| 656 | if ((m->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_UDP)) != 0) |
| 657 | csum_flags = TX_CHECKSUM_CTL_FULL; |
| 658 | else |
| 659 | csum_flags = TX_CHECKSUM_CTL_IP; |
| 660 | flags |= (csum_flags << TX_CHECKSUM_CTL_SHIFT); |
| 661 | } |
no test coverage detected