| 1996 | } |
| 1997 | |
| 1998 | static int |
| 1999 | cpsw_tx_dequeue(struct cpsw_softc *sc) |
| 2000 | { |
| 2001 | struct cpsw_slot *slot, *last_removed_slot = NULL; |
| 2002 | struct cpsw_cpdma_bd bd; |
| 2003 | uint32_t flags, removed = 0; |
| 2004 | |
| 2005 | /* Pull completed buffers off the hardware TX queue. */ |
| 2006 | slot = STAILQ_FIRST(&sc->tx.active); |
| 2007 | while (slot != NULL) { |
| 2008 | flags = cpsw_cpdma_read_bd_flags(sc, slot); |
| 2009 | |
| 2010 | /* TearDown complete is only marked on the SOP for the packet. */ |
| 2011 | if ((flags & (CPDMA_BD_SOP | CPDMA_BD_TDOWNCMPLT)) == |
| 2012 | (CPDMA_BD_SOP | CPDMA_BD_TDOWNCMPLT)) { |
| 2013 | sc->tx.teardown = 1; |
| 2014 | } |
| 2015 | |
| 2016 | if ((flags & (CPDMA_BD_SOP | CPDMA_BD_OWNER)) == |
| 2017 | (CPDMA_BD_SOP | CPDMA_BD_OWNER) && sc->tx.teardown == 0) |
| 2018 | break; /* Hardware is still using this packet. */ |
| 2019 | |
| 2020 | bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap, BUS_DMASYNC_POSTWRITE); |
| 2021 | bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap); |
| 2022 | m_freem(slot->mbuf); |
| 2023 | slot->mbuf = NULL; |
| 2024 | |
| 2025 | if (slot->ifp) { |
| 2026 | if (sc->tx.teardown == 0) |
| 2027 | if_inc_counter(slot->ifp, IFCOUNTER_OPACKETS, 1); |
| 2028 | else |
| 2029 | if_inc_counter(slot->ifp, IFCOUNTER_OQDROPS, 1); |
| 2030 | } |
| 2031 | |
| 2032 | /* Dequeue any additional buffers used by this packet. */ |
| 2033 | while (slot != NULL && slot->mbuf == NULL) { |
| 2034 | STAILQ_REMOVE_HEAD(&sc->tx.active, next); |
| 2035 | STAILQ_INSERT_TAIL(&sc->tx.avail, slot, next); |
| 2036 | ++removed; |
| 2037 | last_removed_slot = slot; |
| 2038 | slot = STAILQ_FIRST(&sc->tx.active); |
| 2039 | } |
| 2040 | |
| 2041 | cpsw_write_cp_slot(sc, &sc->tx, last_removed_slot); |
| 2042 | |
| 2043 | /* Restart the TX queue if necessary. */ |
| 2044 | cpsw_cpdma_read_bd(sc, last_removed_slot, &bd); |
| 2045 | if (slot != NULL && bd.next != 0 && (bd.flags & |
| 2046 | (CPDMA_BD_EOP | CPDMA_BD_OWNER | CPDMA_BD_EOQ)) == |
| 2047 | (CPDMA_BD_EOP | CPDMA_BD_EOQ)) { |
| 2048 | cpsw_write_hdp_slot(sc, &sc->tx, slot); |
| 2049 | sc->tx.queue_restart++; |
| 2050 | break; |
| 2051 | } |
| 2052 | } |
| 2053 | |
| 2054 | if (removed != 0) { |
| 2055 | sc->tx.queue_removes += removed; |
no test coverage detected