summaryrefslogtreecommitdiffstats
path: root/sys/dev/hatm/if_hatm_intr.c
diff options
context:
space:
mode:
authorharti <harti@FreeBSD.org>2003-10-29 12:59:44 +0000
committerharti <harti@FreeBSD.org>2003-10-29 12:59:44 +0000
commit568c57f368a5b09aa3cac9b6d7ddb6fae11059c0 (patch)
tree9d42396102479ef0a920fb92a586c9ed15b548c1 /sys/dev/hatm/if_hatm_intr.c
parent36edae8e0d6caa4c38b5624886e0b8a21fc77870 (diff)
downloadFreeBSD-src-568c57f368a5b09aa3cac9b6d7ddb6fae11059c0.zip
FreeBSD-src-568c57f368a5b09aa3cac9b6d7ddb6fae11059c0.tar.gz
Get rid of the mutexes for the exernal buffer free lists. Use
atomic instructions instead. Remove the stuff used to track whether an external mbuf travels through the system. This is temporary only and will come back soon.
Diffstat (limited to 'sys/dev/hatm/if_hatm_intr.c')
-rw-r--r--sys/dev/hatm/if_hatm_intr.c83
1 files changed, 49 insertions, 34 deletions
diff --git a/sys/dev/hatm/if_hatm_intr.c b/sys/dev/hatm/if_hatm_intr.c
index 80347d1..9379026 100644
--- a/sys/dev/hatm/if_hatm_intr.c
+++ b/sys/dev/hatm/if_hatm_intr.c
@@ -83,6 +83,45 @@ CTASSERT(sizeof(((struct mbuf0_chunk *)NULL)->storage) >= MBUF0_SIZE);
CTASSERT(sizeof(((struct mbuf1_chunk *)NULL)->storage) >= MBUF1_SIZE);
CTASSERT(sizeof(struct tpd) <= HE_TPD_SIZE);
+static void hatm_mbuf_page_alloc(struct hatm_softc *sc, u_int group);
+
+/*
+ * Free an external mbuf to a list. We use atomic functions so that
+ * we don't need a mutex for the list.
+ */
+static __inline void
+hatm_ext_free(struct mbufx_free **list, struct mbufx_free *buf)
+{
+ for (;;) {
+ buf->link = *list;
+ if (atomic_cmpset_ptr(list, buf->link, buf))
+ break;
+ }
+}
+
+static __inline struct mbufx_free *
+hatm_ext_alloc(struct hatm_softc *sc, u_int g)
+{
+ struct mbufx_free *buf;
+
+ for (;;) {
+ if ((buf = sc->mbuf_list[g]) == NULL)
+ break;
+ if (atomic_cmpset_ptr(&sc->mbuf_list[g], buf, buf->link))
+ break;
+ }
+ if (buf == NULL) {
+ hatm_mbuf_page_alloc(sc, g);
+ for (;;) {
+ if ((buf = sc->mbuf_list[g]) == NULL)
+ break;
+ if (atomic_cmpset_ptr(&sc->mbuf_list[g], buf, buf->link))
+ break;
+ }
+ }
+ return (buf);
+}
+
/*
* Either the queue treshold was crossed or a TPD with the INTR bit set
* was transmitted.
@@ -141,7 +180,6 @@ hatm_mbuf_page_alloc(struct hatm_softc *sc, u_int group)
if ((pg = malloc(MBUF_ALLOC_SIZE, M_DEVBUF, M_NOWAIT)) == NULL)
return;
bzero(pg->hdr.card, sizeof(pg->hdr.card));
- bzero(pg->hdr.used, sizeof(pg->hdr.used));
err = bus_dmamap_create(sc->mbuf_tag, 0, &pg->hdr.map);
if (err != 0) {
@@ -172,8 +210,8 @@ hatm_mbuf_page_alloc(struct hatm_softc *sc, u_int group)
for (i = 0; i < MBUF0_PER_PAGE; i++, c++) {
c->hdr.pageno = sc->mbuf_npages;
c->hdr.chunkno = i;
- SLIST_INSERT_HEAD(&sc->mbuf0_list,
- (struct mbufx_free *)c, link);
+ hatm_ext_free(&sc->mbuf_list[0],
+ (struct mbufx_free *)c);
}
} else {
struct mbuf1_chunk *c;
@@ -185,8 +223,8 @@ hatm_mbuf_page_alloc(struct hatm_softc *sc, u_int group)
for (i = 0; i < MBUF1_PER_PAGE; i++, c++) {
c->hdr.pageno = sc->mbuf_npages;
c->hdr.chunkno = i;
- SLIST_INSERT_HEAD(&sc->mbuf1_list,
- (struct mbufx_free *)c, link);
+ hatm_ext_free(&sc->mbuf_list[1],
+ (struct mbufx_free *)c);
}
}
sc->mbuf_npages++;
@@ -201,10 +239,7 @@ hatm_mbuf0_free(void *buf, void *args)
struct hatm_softc *sc = args;
struct mbuf0_chunk *c = buf;
- mtx_lock(&sc->mbuf0_mtx);
- SLIST_INSERT_HEAD(&sc->mbuf0_list, (struct mbufx_free *)c, link);
- MBUF_CLR_BIT(sc->mbuf_pages[c->hdr.pageno]->hdr.used, c->hdr.chunkno);
- mtx_unlock(&sc->mbuf0_mtx);
+ hatm_ext_free(&sc->mbuf_list[0], (struct mbufx_free *)c);
}
static void
hatm_mbuf1_free(void *buf, void *args)
@@ -212,10 +247,7 @@ hatm_mbuf1_free(void *buf, void *args)
struct hatm_softc *sc = args;
struct mbuf1_chunk *c = buf;
- mtx_lock(&sc->mbuf1_mtx);
- SLIST_INSERT_HEAD(&sc->mbuf1_list, (struct mbufx_free *)c, link);
- MBUF_CLR_BIT(sc->mbuf_pages[c->hdr.pageno]->hdr.used, c->hdr.chunkno);
- mtx_unlock(&sc->mbuf1_mtx);
+ hatm_ext_free(&sc->mbuf_list[1], (struct mbufx_free *)c);
}
/*
@@ -231,19 +263,11 @@ hatm_mbuf_alloc(struct hatm_softc *sc, u_int group, struct mbuf *m,
if (group == 0) {
struct mbuf0_chunk *buf0;
- mtx_lock(&sc->mbuf0_mtx);
- if ((cf = SLIST_FIRST(&sc->mbuf0_list)) == NULL) {
- hatm_mbuf_page_alloc(sc, group);
- if ((cf = SLIST_FIRST(&sc->mbuf0_list)) == NULL) {
- mtx_unlock(&sc->mbuf0_mtx);
- return (-1);
- }
- }
- SLIST_REMOVE_HEAD(&sc->mbuf0_list, link);
+ if ((cf = hatm_ext_alloc(sc, 0)) == NULL)
+ return (-1);
buf0 = (struct mbuf0_chunk *)cf;
pg = sc->mbuf_pages[buf0->hdr.pageno];
MBUF_SET_BIT(pg->hdr.card, buf0->hdr.chunkno);
- mtx_unlock(&sc->mbuf0_mtx);
m_extadd(m, (caddr_t)buf0, MBUF0_SIZE, hatm_mbuf0_free, sc,
M_PKTHDR, EXT_NET_DRV);
@@ -255,19 +279,11 @@ hatm_mbuf_alloc(struct hatm_softc *sc, u_int group, struct mbuf *m,
} else if (group == 1) {
struct mbuf1_chunk *buf1;
- mtx_lock(&sc->mbuf1_mtx);
- if ((cf = SLIST_FIRST(&sc->mbuf1_list)) == NULL) {
- hatm_mbuf_page_alloc(sc, group);
- if ((cf = SLIST_FIRST(&sc->mbuf1_list)) == NULL) {
- mtx_unlock(&sc->mbuf1_mtx);
- return (-1);
- }
- }
- SLIST_REMOVE_HEAD(&sc->mbuf1_list, link);
+ if ((cf = hatm_ext_alloc(sc, 1)) == NULL)
+ return (-1);
buf1 = (struct mbuf1_chunk *)cf;
pg = sc->mbuf_pages[buf1->hdr.pageno];
MBUF_SET_BIT(pg->hdr.card, buf1->hdr.chunkno);
- mtx_unlock(&sc->mbuf1_mtx);
m_extadd(m, (caddr_t)buf1, MBUF1_SIZE, hatm_mbuf1_free, sc,
M_PKTHDR, EXT_NET_DRV);
@@ -431,7 +447,6 @@ hatm_rx_buffer(struct hatm_softc *sc, u_int group, u_int handle)
m = c1->hdr.mbuf;
}
MBUF_CLR_BIT(sc->mbuf_pages[pageno]->hdr.card, chunkno);
- MBUF_SET_BIT(sc->mbuf_pages[pageno]->hdr.used, chunkno);
bus_dmamap_sync(sc->mbuf_tag, sc->mbuf_pages[pageno]->hdr.map,
BUS_DMASYNC_POSTREAD);
OpenPOWER on IntegriCloud