From 079e5a8053bea01154a0d15506fad08b72beb28b Mon Sep 17 00:00:00 2001 From: jmg Date: Mon, 15 Nov 2004 19:37:21 +0000 Subject: fix the missing lock in sk_jfree (verified w/ an assert) also fix up handling and proding of the tx, _OACTIVE is now handled better... Submitted by: Peter Edwards (sk_jfree) Obtained from: OpenBSD and/or NetBSD (tx prod) --- sys/dev/sk/if_sk.c | 32 ++++++++++++++++++++++---------- sys/dev/sk/if_skreg.h | 1 + sys/pci/if_sk.c | 32 ++++++++++++++++++++++---------- sys/pci/if_skreg.h | 1 + 4 files changed, 46 insertions(+), 20 deletions(-) (limited to 'sys') diff --git a/sys/dev/sk/if_sk.c b/sys/dev/sk/if_sk.c index 7f577d7..2bc4f15 100644 --- a/sys/dev/sk/if_sk.c +++ b/sys/dev/sk/if_sk.c @@ -1075,9 +1075,11 @@ sk_jalloc(sc_if) struct sk_if_softc *sc_if; { struct sk_jpool_entry *entry; - + + SK_IF_LOCK_ASSERT(sc_if); + entry = SLIST_FIRST(&sc_if->sk_jfree_listhead); - + if (entry == NULL) { #ifdef SK_VERBOSE printf("sk%d: no free jumbo buffers\n", sc_if->sk_unit); @@ -1104,6 +1106,7 @@ sk_jfree(buf, args) /* Extract the softc struct pointer. */ sc_if = (struct sk_if_softc *)args; + SK_IF_LOCK(sc_if); if (sc_if == NULL) panic("sk_jfree: didn't get softc pointer!"); @@ -1122,6 +1125,7 @@ sk_jfree(buf, args) SLIST_REMOVE_HEAD(&sc_if->sk_jinuse_listhead, jpool_entries); SLIST_INSERT_HEAD(&sc_if->sk_jfree_listhead, entry, jpool_entries); + SK_IF_UNLOCK(sc_if); return; } @@ -1781,6 +1785,8 @@ sk_encap(sc_if, m_head, txidx) struct mbuf *m; u_int32_t frag, cur, cnt = 0; + SK_IF_LOCK_ASSERT(sc_if); + m = m_head; cur = frag = *txidx; @@ -1861,11 +1867,13 @@ sk_start(ifp) } /* Transmit */ - sc_if->sk_cdata.sk_tx_prod = idx; - CSR_WRITE_4(sc, sc_if->sk_tx_bmu, SK_TXBMU_TX_START); + if (idx != sc_if->sk_cdata.sk_tx_prod) { + sc_if->sk_cdata.sk_tx_prod = idx; + CSR_WRITE_4(sc, sc_if->sk_tx_bmu, SK_TXBMU_TX_START); - /* Set a timeout in case the chip goes out to lunch. */ - ifp->if_timer = 5; + /* Set a timeout in case the chip goes out to lunch. */ + ifp->if_timer = 5; + } SK_IF_UNLOCK(sc_if); return; @@ -1982,10 +1990,12 @@ static void sk_txeof(sc_if) struct sk_if_softc *sc_if; { + struct sk_softc *sc; struct sk_tx_desc *cur_tx = NULL; struct ifnet *ifp; u_int32_t idx; + sc = sc_if->sk_softc; ifp = &sc_if->arpcom.ac_if; /* @@ -2005,13 +2015,15 @@ sk_txeof(sc_if) } sc_if->sk_cdata.sk_tx_cnt--; SK_INC(idx, SK_TX_RING_CNT); - ifp->if_timer = 0; } - sc_if->sk_cdata.sk_tx_cons = idx; - - if (cur_tx != NULL) + if (sc_if->sk_cdata.sk_tx_cnt == 0) { + ifp->if_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; + } else /* nudge chip to keep tx ring moving */ + CSR_WRITE_4(sc, sc_if->sk_tx_bmu, SK_TXBMU_TX_START); + + sc_if->sk_cdata.sk_tx_cons = idx; return; } diff --git a/sys/dev/sk/if_skreg.h b/sys/dev/sk/if_skreg.h index 8271c03..b70e172 100644 --- a/sys/dev/sk/if_skreg.h +++ b/sys/dev/sk/if_skreg.h @@ -1442,6 +1442,7 @@ struct sk_softc { #define SK_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sk_mtx, MA_OWNED) #define SK_IF_LOCK(_sc) SK_LOCK((_sc)->sk_softc) #define SK_IF_UNLOCK(_sc) SK_UNLOCK((_sc)->sk_softc) +#define SK_IF_LOCK_ASSERT(_sc) SK_LOCK_ASSERT((_sc)->sk_softc) /* Softc for each logical interface */ struct sk_if_softc { diff --git a/sys/pci/if_sk.c b/sys/pci/if_sk.c index 7f577d7..2bc4f15 100644 --- a/sys/pci/if_sk.c +++ b/sys/pci/if_sk.c @@ -1075,9 +1075,11 @@ sk_jalloc(sc_if) struct sk_if_softc *sc_if; { struct sk_jpool_entry *entry; - + + SK_IF_LOCK_ASSERT(sc_if); + entry = SLIST_FIRST(&sc_if->sk_jfree_listhead); - + if (entry == NULL) { #ifdef SK_VERBOSE printf("sk%d: no free jumbo buffers\n", sc_if->sk_unit); @@ -1104,6 +1106,7 @@ sk_jfree(buf, args) /* Extract the softc struct pointer. */ sc_if = (struct sk_if_softc *)args; + SK_IF_LOCK(sc_if); if (sc_if == NULL) panic("sk_jfree: didn't get softc pointer!"); @@ -1122,6 +1125,7 @@ sk_jfree(buf, args) SLIST_REMOVE_HEAD(&sc_if->sk_jinuse_listhead, jpool_entries); SLIST_INSERT_HEAD(&sc_if->sk_jfree_listhead, entry, jpool_entries); + SK_IF_UNLOCK(sc_if); return; } @@ -1781,6 +1785,8 @@ sk_encap(sc_if, m_head, txidx) struct mbuf *m; u_int32_t frag, cur, cnt = 0; + SK_IF_LOCK_ASSERT(sc_if); + m = m_head; cur = frag = *txidx; @@ -1861,11 +1867,13 @@ sk_start(ifp) } /* Transmit */ - sc_if->sk_cdata.sk_tx_prod = idx; - CSR_WRITE_4(sc, sc_if->sk_tx_bmu, SK_TXBMU_TX_START); + if (idx != sc_if->sk_cdata.sk_tx_prod) { + sc_if->sk_cdata.sk_tx_prod = idx; + CSR_WRITE_4(sc, sc_if->sk_tx_bmu, SK_TXBMU_TX_START); - /* Set a timeout in case the chip goes out to lunch. */ - ifp->if_timer = 5; + /* Set a timeout in case the chip goes out to lunch. */ + ifp->if_timer = 5; + } SK_IF_UNLOCK(sc_if); return; @@ -1982,10 +1990,12 @@ static void sk_txeof(sc_if) struct sk_if_softc *sc_if; { + struct sk_softc *sc; struct sk_tx_desc *cur_tx = NULL; struct ifnet *ifp; u_int32_t idx; + sc = sc_if->sk_softc; ifp = &sc_if->arpcom.ac_if; /* @@ -2005,13 +2015,15 @@ sk_txeof(sc_if) } sc_if->sk_cdata.sk_tx_cnt--; SK_INC(idx, SK_TX_RING_CNT); - ifp->if_timer = 0; } - sc_if->sk_cdata.sk_tx_cons = idx; - - if (cur_tx != NULL) + if (sc_if->sk_cdata.sk_tx_cnt == 0) { + ifp->if_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; + } else /* nudge chip to keep tx ring moving */ + CSR_WRITE_4(sc, sc_if->sk_tx_bmu, SK_TXBMU_TX_START); + + sc_if->sk_cdata.sk_tx_cons = idx; return; } diff --git a/sys/pci/if_skreg.h b/sys/pci/if_skreg.h index 8271c03..b70e172 100644 --- a/sys/pci/if_skreg.h +++ b/sys/pci/if_skreg.h @@ -1442,6 +1442,7 @@ struct sk_softc { #define SK_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sk_mtx, MA_OWNED) #define SK_IF_LOCK(_sc) SK_LOCK((_sc)->sk_softc) #define SK_IF_UNLOCK(_sc) SK_UNLOCK((_sc)->sk_softc) +#define SK_IF_LOCK_ASSERT(_sc) SK_LOCK_ASSERT((_sc)->sk_softc) /* Softc for each logical interface */ struct sk_if_softc { -- cgit v1.1