| 1612 | } |
| 1613 | |
| 1614 | static struct mbuf * |
| 1615 | cpsw_rx_dequeue(struct cpsw_softc *sc) |
| 1616 | { |
| 1617 | int nsegs, port, removed; |
| 1618 | struct cpsw_cpdma_bd bd; |
| 1619 | struct cpsw_slot *last, *slot; |
| 1620 | struct cpswp_softc *psc; |
| 1621 | struct mbuf *m, *m0, *mb_head, *mb_tail; |
| 1622 | uint16_t m0_flags; |
| 1623 | |
| 1624 | nsegs = 0; |
| 1625 | m0 = NULL; |
| 1626 | last = NULL; |
| 1627 | mb_head = NULL; |
| 1628 | mb_tail = NULL; |
| 1629 | removed = 0; |
| 1630 | |
| 1631 | /* Pull completed packets off hardware RX queue. */ |
| 1632 | while ((slot = STAILQ_FIRST(&sc->rx.active)) != NULL) { |
| 1633 | cpsw_cpdma_read_bd(sc, slot, &bd); |
| 1634 | |
| 1635 | /* |
| 1636 | * Stop on packets still in use by hardware, but do not stop |
| 1637 | * on packets with the teardown complete flag, they will be |
| 1638 | * discarded later. |
| 1639 | */ |
| 1640 | if ((bd.flags & (CPDMA_BD_OWNER | CPDMA_BD_TDOWNCMPLT)) == |
| 1641 | CPDMA_BD_OWNER) |
| 1642 | break; |
| 1643 | |
| 1644 | last = slot; |
| 1645 | ++removed; |
| 1646 | STAILQ_REMOVE_HEAD(&sc->rx.active, next); |
| 1647 | STAILQ_INSERT_TAIL(&sc->rx.avail, slot, next); |
| 1648 | |
| 1649 | bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap, BUS_DMASYNC_POSTREAD); |
| 1650 | bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap); |
| 1651 | |
| 1652 | m = slot->mbuf; |
| 1653 | slot->mbuf = NULL; |
| 1654 | |
| 1655 | if (bd.flags & CPDMA_BD_TDOWNCMPLT) { |
| 1656 | CPSW_DEBUGF(sc, ("RX teardown is complete")); |
| 1657 | m_freem(m); |
| 1658 | sc->rx.running = 0; |
| 1659 | sc->rx.teardown = 0; |
| 1660 | break; |
| 1661 | } |
| 1662 | |
| 1663 | port = (bd.flags & CPDMA_BD_PORT_MASK) - 1; |
| 1664 | KASSERT(port >= 0 && port <= 1, |
| 1665 | ("patcket received with invalid port: %d", port)); |
| 1666 | psc = device_get_softc(sc->port[port].dev); |
| 1667 | |
| 1668 | /* Set up mbuf */ |
| 1669 | m->m_data += bd.bufoff; |
| 1670 | m->m_len = bd.buflen; |
| 1671 | if (bd.flags & CPDMA_BD_SOP) { |
no test coverage detected