Index: sys/pool.h =================================================================== RCS file: /cvs/src/sys/sys/pool.h,v retrieving revision 1.54 diff -u -p -r1.54 pool.h --- sys/pool.h 1 Nov 2014 23:58:07 -0000 1.54 +++ sys/pool.h 15 Dec 2014 13:30:44 -0000 @@ -82,7 +82,7 @@ struct pool_allocator { int pa_pagesz; }; -LIST_HEAD(pool_pagelist, pool_item_header); +TAILQ_HEAD(pool_pagelist, pool_item_header); struct pool { struct mutex pr_mtx; @@ -189,7 +189,7 @@ void pool_set_constraints(struct pool * void *pool_get(struct pool *, int) __malloc; void pool_request_init(struct pool_request *, void (*)(void *, void *), void *); -void pool_request(struct pool *, struct pool_request *); +void pool_request(struct pool *, struct pool_request *, int); void pool_put(struct pool *, void *); int pool_reclaim(struct pool *); void pool_reclaim_all(void); Index: kern/subr_pool.c =================================================================== RCS file: /cvs/src/sys/kern/subr_pool.c,v retrieving revision 1.169 diff -u -p -r1.169 subr_pool.c --- kern/subr_pool.c 4 Dec 2014 03:12:05 -0000 1.169 +++ kern/subr_pool.c 15 Dec 2014 13:30:44 -0000 @@ -32,6 +32,7 @@ */ #include +#include #include #include #include @@ -74,7 +75,7 @@ struct pool phpool; struct pool_item_header { /* Page headers */ - LIST_ENTRY(pool_item_header) + TAILQ_ENTRY(pool_item_header) ph_pagelist; /* pool page list */ XSIMPLEQ_HEAD(,pool_item) ph_itemlist; /* chunk list for this page */ RB_ENTRY(pool_item_header) @@ -82,6 +83,7 @@ struct pool_item_header { int ph_nmissing; /* # of chunks in use */ caddr_t ph_page; /* this page's address */ u_long ph_magic; + int ph_tick; }; #define POOL_MAGICBIT (1 << 3) /* keep away from perturbed low bits */ #define POOL_PHPOISON(ph) ISSET((ph)->ph_magic, POOL_MAGICBIT) @@ -231,7 +233,7 @@ pool_init(struct pool *pp, size_t size, size = roundup(size, align); if (palloc == NULL) { - while (size > pgsize) + while (size * 8 > pgsize) pgsize <<= 1; if (pgsize > PAGE_SIZE) { @@ -263,9 +265,9 @@ pool_init(struct pool *pp, size_t size, * Initialize the pool structure. */ memset(pp, 0, sizeof(*pp)); - LIST_INIT(&pp->pr_emptypages); - LIST_INIT(&pp->pr_fullpages); - LIST_INIT(&pp->pr_partpages); + TAILQ_INIT(&pp->pr_emptypages); + TAILQ_INIT(&pp->pr_fullpages); + TAILQ_INIT(&pp->pr_partpages); pp->pr_curpage = NULL; pp->pr_npages = 0; pp->pr_minitems = 0; @@ -375,14 +377,14 @@ pool_destroy(struct pool *pp) rw_exit_write(&pool_lock); /* Remove all pages */ - while ((ph = LIST_FIRST(&pp->pr_emptypages)) != NULL) { + while ((ph = TAILQ_FIRST(&pp->pr_emptypages)) != NULL) { mtx_enter(&pp->pr_mtx); pool_p_remove(pp, ph); mtx_leave(&pp->pr_mtx); pool_p_free(pp, ph); } - KASSERT(LIST_EMPTY(&pp->pr_fullpages)); - KASSERT(LIST_EMPTY(&pp->pr_partpages)); + KASSERT(TAILQ_EMPTY(&pp->pr_fullpages)); + KASSERT(TAILQ_EMPTY(&pp->pr_partpages)); } void @@ -395,19 +397,14 @@ pool_request_init(struct pool_request *p } void -pool_request(struct pool *pp, struct pool_request *pr) +pool_request(struct pool *pp, struct pool_request *pr, int flags) { mtx_enter(&pp->pr_requests_mtx); TAILQ_INSERT_TAIL(&pp->pr_requests, pr, pr_entry); - pool_runqueue(pp, PR_NOWAIT); + pool_runqueue(pp, flags); mtx_leave(&pp->pr_requests_mtx); } -struct pool_get_memory { - struct mutex mtx; - void * volatile v; -}; - /* * Grab an item from the pool. */ @@ -419,36 +416,33 @@ pool_get(struct pool *pp, int flags) KASSERT(flags & (PR_WAITOK | PR_NOWAIT)); + if ((flags & (PR_WAITOK|PR_LIMITFAIL)) != PR_WAITOK) { + mtx_enter(&pp->pr_mtx); + if (pp->pr_nout >= pp->pr_hardlimit) { + if (ISSET(flags, PR_NOWAIT|PR_LIMITFAIL)) + goto fail; + } else if ((v = pool_do_get(pp, flags, &slowdown)) == NULL) { + if (ISSET(flags, PR_NOWAIT)) + goto fail; + } + mtx_leave(&pp->pr_mtx); - mtx_enter(&pp->pr_mtx); - if (pp->pr_nout >= pp->pr_hardlimit) { - if (ISSET(flags, PR_NOWAIT|PR_LIMITFAIL)) - goto fail; - } else if ((v = pool_do_get(pp, flags, &slowdown)) == NULL) { - if (ISSET(flags, PR_NOWAIT)) - goto fail; + if (slowdown && ISSET(flags, PR_WAITOK)) + yield(); } - mtx_leave(&pp->pr_mtx); - - if (slowdown && ISSET(flags, PR_WAITOK)) - yield(); - if (v == NULL) { - struct pool_get_memory mem = { - MUTEX_INITIALIZER((pp->pr_ipl == -1) ? - IPL_NONE : pp->pr_ipl), NULL }; + if (v == NULL) { + struct sleep_state sls; struct pool_request pr; - - pool_request_init(&pr, pool_get_done, &mem); - pool_request(pp, &pr); - - mtx_enter(&mem.mtx); - while (mem.v == NULL) - msleep(&mem, &mem.mtx, PSWP, pp->pr_wchan, 0); - mtx_leave(&mem.mtx); - - v = mem.v; - } + + pool_request_init(&pr, pool_get_done, &v); + pool_request(pp, &pr, flags); + + while (v == NULL) { + sleep_setup(&sls, &v, PWAIT, pp->pr_wchan); + sleep_finish(&sls, (v == NULL)); + } + } if (ISSET(flags, PR_ZERO)) memset(v, 0, pp->pr_size); @@ -462,15 +456,12 @@ fail: } void -pool_get_done(void *xmem, void *v) +pool_get_done(void *ctx, void *v) { - struct pool_get_memory *mem = xmem; + void **vp = ctx; - mtx_enter(&mem->mtx); - mem->v = v; - mtx_leave(&mem->mtx); - - wakeup_one(mem); + *vp = v; + wakeup_one(vp); } void @@ -486,6 +477,7 @@ pool_runqueue(struct pool *pp, int flags return; do { + int slowdown = 0; pp->pr_requesting = 1; /* no TAILQ_JOIN? :( */ @@ -501,19 +493,20 @@ pool_runqueue(struct pool *pp, int flags mtx_enter(&pp->pr_mtx); pr = TAILQ_FIRST(&prl); while (pr != NULL) { - int slowdown = 0; - if (pp->pr_nout >= pp->pr_hardlimit) break; pr->pr_item = pool_do_get(pp, flags, &slowdown); - if (pr->pr_item == NULL) /* || slowdown ? */ + if (pr->pr_item == NULL) break; pr = TAILQ_NEXT(pr, pr_entry); } mtx_leave(&pp->pr_mtx); + if (slowdown && ISSET(flags, PR_WAITOK)) + yield(); + while ((pr = TAILQ_FIRST(&prl)) != NULL && pr->pr_item != NULL) { TAILQ_REMOVE(&prl, pr, pr_entry); @@ -591,8 +584,8 @@ pool_do_get(struct pool *pp, int flags, * This page was previously empty. Move it to the list of * partially-full pages. This page is already curpage. */ - LIST_REMOVE(ph, ph_pagelist); - LIST_INSERT_HEAD(&pp->pr_partpages, ph, ph_pagelist); + TAILQ_REMOVE(&pp->pr_emptypages, ph, ph_pagelist); + TAILQ_INSERT_HEAD(&pp->pr_partpages, ph, ph_pagelist); pp->pr_nidle--; } @@ -602,8 +595,8 @@ pool_do_get(struct pool *pp, int flags, * This page is now full. Move it to the full list * and select a new current page. */ - LIST_REMOVE(ph, ph_pagelist); - LIST_INSERT_HEAD(&pp->pr_fullpages, ph, ph_pagelist); + TAILQ_REMOVE(&pp->pr_partpages, ph, ph_pagelist); + TAILQ_INSERT_HEAD(&pp->pr_fullpages, ph, ph_pagelist); pool_update_curpage(pp); } @@ -620,6 +613,7 @@ pool_put(struct pool *pp, void *v) { struct pool_item *pi = v; struct pool_item_header *ph, *freeph = NULL; + extern int ticks; #ifdef DIAGNOSTIC if (v == NULL) @@ -654,8 +648,8 @@ pool_put(struct pool *pp, void *v) * The page was previously completely full, move it to the * partially-full list. */ - LIST_REMOVE(ph, ph_pagelist); - LIST_INSERT_HEAD(&pp->pr_partpages, ph, ph_pagelist); + TAILQ_REMOVE(&pp->pr_fullpages, ph, ph_pagelist); + TAILQ_INSERT_HEAD(&pp->pr_partpages, ph, ph_pagelist); } if (ph->ph_nmissing == 0) { @@ -664,8 +658,9 @@ pool_put(struct pool *pp, void *v) */ pp->pr_nidle++; - LIST_REMOVE(ph, ph_pagelist); - LIST_INSERT_HEAD(&pp->pr_emptypages, ph, ph_pagelist); + ph->ph_tick = ticks; + TAILQ_REMOVE(&pp->pr_partpages, ph, ph_pagelist); + TAILQ_INSERT_TAIL(&pp->pr_emptypages, ph, ph_pagelist); pool_update_curpage(pp); } @@ -674,8 +669,11 @@ pool_put(struct pool *pp, void *v) /* is it time to free a page? */ if (pp->pr_nidle > pp->pr_maxpages && - (freeph = LIST_FIRST(&pp->pr_emptypages)) != NULL) + (ph = TAILQ_FIRST(&pp->pr_emptypages)) != NULL && + (ticks - ph->ph_tick) > hz) { + freeph = ph; pool_p_remove(pp, freeph); + } mtx_leave(&pp->pr_mtx); if (freeph != NULL) @@ -692,7 +690,7 @@ pool_put(struct pool *pp, void *v) int pool_prime(struct pool *pp, int n) { - struct pool_pagelist pl = LIST_HEAD_INITIALIZER(pl); + struct pool_pagelist pl = TAILQ_HEAD_INITIALIZER(pl); struct pool_item_header *ph; int newpages; @@ -705,12 +703,12 @@ pool_prime(struct pool *pp, int n) if (ph == NULL) /* or slowdown? */ break; - LIST_INSERT_HEAD(&pl, ph, ph_pagelist); + TAILQ_INSERT_HEAD(&pl, ph, ph_pagelist); } mtx_enter(&pp->pr_mtx); - while ((ph = LIST_FIRST(&pl)) != NULL) { - LIST_REMOVE(ph, ph_pagelist); + while ((ph = TAILQ_FIRST(&pl)) != NULL) { + TAILQ_REMOVE(&pl, ph, ph_pagelist); pool_p_insert(pp, ph); } mtx_leave(&pp->pr_mtx); @@ -819,7 +817,7 @@ pool_p_insert(struct pool *pp, struct po if (pp->pr_curpage == NULL) pp->pr_curpage = ph; - LIST_INSERT_HEAD(&pp->pr_emptypages, ph, ph_pagelist); + TAILQ_INSERT_HEAD(&pp->pr_emptypages, ph, ph_pagelist); if (!POOL_INPGHDR(pp)) RB_INSERT(phtree, &pp->pr_phtree, ph); @@ -843,7 +841,7 @@ pool_p_remove(struct pool *pp, struct po if (!POOL_INPGHDR(pp)) RB_REMOVE(phtree, &pp->pr_phtree, ph); - LIST_REMOVE(ph, ph_pagelist); + TAILQ_REMOVE(&pp->pr_emptypages, ph, ph_pagelist); pool_update_curpage(pp); } @@ -851,10 +849,9 @@ pool_p_remove(struct pool *pp, struct po void pool_update_curpage(struct pool *pp) { - pp->pr_curpage = LIST_FIRST(&pp->pr_partpages); - if (pp->pr_curpage == NULL) { - pp->pr_curpage = LIST_FIRST(&pp->pr_emptypages); - } + pp->pr_curpage = TAILQ_FIRST(&pp->pr_partpages); + if (pp->pr_curpage == NULL) + pp->pr_curpage = TAILQ_FIRST(&pp->pr_emptypages); } void @@ -919,11 +916,11 @@ int pool_reclaim(struct pool *pp) { struct pool_item_header *ph, *phnext; - struct pool_pagelist pl = LIST_HEAD_INITIALIZER(pl); + struct pool_pagelist pl = TAILQ_HEAD_INITIALIZER(pl); mtx_enter(&pp->pr_mtx); - for (ph = LIST_FIRST(&pp->pr_emptypages); ph != NULL; ph = phnext) { - phnext = LIST_NEXT(ph, ph_pagelist); + for (ph = TAILQ_FIRST(&pp->pr_emptypages); ph != NULL; ph = phnext) { + phnext = TAILQ_NEXT(ph, ph_pagelist); /* Check our minimum page claim */ if (pp->pr_npages <= pp->pr_minpages) @@ -938,15 +935,15 @@ pool_reclaim(struct pool *pp) break; pool_p_remove(pp, ph); - LIST_INSERT_HEAD(&pl, ph, ph_pagelist); + TAILQ_INSERT_HEAD(&pl, ph, ph_pagelist); } mtx_leave(&pp->pr_mtx); - if (LIST_EMPTY(&pl)) + if (TAILQ_EMPTY(&pl)) return (0); - while ((ph = LIST_FIRST(&pl)) != NULL) { - LIST_REMOVE(ph, ph_pagelist); + while ((ph = TAILQ_FIRST(&pl)) != NULL) { + TAILQ_REMOVE(&pl, ph, ph_pagelist); pool_p_free(pp, ph); } @@ -990,7 +987,7 @@ pool_print_pagelist(struct pool_pagelist struct pool_item_header *ph; struct pool_item *pi; - LIST_FOREACH(ph, pl, ph_pagelist) { + TAILQ_FOREACH(ph, pl, ph_pagelist) { (*pr)("\t\tpage %p, nmissing %d\n", ph->ph_page, ph->ph_nmissing); XSIMPLEQ_FOREACH(pi, &ph->ph_itemlist, pi_list) { @@ -1033,13 +1030,13 @@ pool_print1(struct pool *pp, const char if (print_pagelist == 0) return; - if ((ph = LIST_FIRST(&pp->pr_emptypages)) != NULL) + if ((ph = TAILQ_FIRST(&pp->pr_emptypages)) != NULL) (*pr)("\n\tempty page list:\n"); pool_print_pagelist(&pp->pr_emptypages, pr); - if ((ph = LIST_FIRST(&pp->pr_fullpages)) != NULL) + if ((ph = TAILQ_FIRST(&pp->pr_fullpages)) != NULL) (*pr)("\n\tfull page list:\n"); pool_print_pagelist(&pp->pr_fullpages, pr); - if ((ph = LIST_FIRST(&pp->pr_partpages)) != NULL) + if ((ph = TAILQ_FIRST(&pp->pr_partpages)) != NULL) (*pr)("\n\tpartial-page list:\n"); pool_print_pagelist(&pp->pr_partpages, pr); @@ -1203,11 +1200,11 @@ pool_chk(struct pool *pp) struct pool_item_header *ph; int r = 0; - LIST_FOREACH(ph, &pp->pr_emptypages, ph_pagelist) + TAILQ_FOREACH(ph, &pp->pr_emptypages, ph_pagelist) r += pool_chk_page(pp, ph, pp->pr_itemsperpage); - LIST_FOREACH(ph, &pp->pr_fullpages, ph_pagelist) + TAILQ_FOREACH(ph, &pp->pr_fullpages, ph_pagelist) r += pool_chk_page(pp, ph, 0); - LIST_FOREACH(ph, &pp->pr_partpages, ph_pagelist) + TAILQ_FOREACH(ph, &pp->pr_partpages, ph_pagelist) r += pool_chk_page(pp, ph, -1); return (r); @@ -1226,7 +1223,7 @@ pool_walk(struct pool *pp, int full, caddr_t cp; int n; - LIST_FOREACH(ph, &pp->pr_fullpages, ph_pagelist) { + TAILQ_FOREACH(ph, &pp->pr_fullpages, ph_pagelist) { cp = ph->ph_page; n = ph->ph_nmissing; @@ -1236,7 +1233,7 @@ pool_walk(struct pool *pp, int full, } } - LIST_FOREACH(ph, &pp->pr_partpages, ph_pagelist) { + TAILQ_FOREACH(ph, &pp->pr_partpages, ph_pagelist) { cp = ph->ph_page; n = ph->ph_nmissing; Index: dev/pci/if_ix.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_ix.c,v retrieving revision 1.112 diff -u -p -r1.112 if_ix.c --- dev/pci/if_ix.c 13 Dec 2014 21:05:33 -0000 1.112 +++ dev/pci/if_ix.c 15 Dec 2014 13:30:44 -0000 @@ -167,6 +167,9 @@ struct cfattach ix_ca = { int ixgbe_smart_speed = ixgbe_smart_speed_on; +#define IX_MCLBYTES MCLBYTES +struct pool *ix_mcl_pool; + /********************************************************************* * Device identification routine * @@ -207,6 +210,17 @@ ixgbe_attach(struct device *parent, stru INIT_DEBUGOUT("ixgbe_attach: begin"); + if (ix_mcl_pool == NULL) { + extern struct kmem_pa_mode kp_dma_contig; + + ix_mcl_pool = malloc(sizeof(*ix_mcl_pool), M_DEVBUF, + M_WAITOK | M_ZERO); + pool_init(ix_mcl_pool, IX_MCLBYTES + ETHER_ALIGN, 64, 0, 0, + "ixmcl", NULL); + pool_setipl(ix_mcl_pool, IPL_NET); + pool_set_constraints(ix_mcl_pool, &kp_dma_contig); + } + sc->osdep.os_sc = sc; sc->osdep.os_pa = *pa; @@ -498,7 +512,7 @@ ixgbe_rxrinfo(struct ix_softc *sc, struc for (i = 0; i < sc->num_queues; i++) { rxr = &sc->rx_rings[i]; - ifr[n].ifr_size = MCLBYTES; + ifr[n].ifr_size = IX_MCLBYTES; snprintf(ifr[n].ifr_name, sizeof(ifr[n].ifr_name), "/%d", i); ifr[n].ifr_info = rxr->rx_ring; n++; @@ -618,7 +632,7 @@ ixgbe_init(void *arg) ixgbe_initialize_transmit_units(sc); /* Use 2k clusters, even for jumbo frames */ - sc->rx_mbuf_sz = MCLBYTES; + sc->rx_mbuf_sz = IX_MCLBYTES; /* Prepare receive descriptors and buffers */ if (ixgbe_setup_receive_structures(sc)) { @@ -2420,6 +2434,7 @@ ixgbe_get_buf(struct rx_ring *rxr, int i int error; union ixgbe_adv_rx_desc *rxdesc; size_t dsize = sizeof(union ixgbe_adv_rx_desc); + void *mcl; rxbuf = &rxr->rx_buffers[i]; rxdesc = &rxr->rx_base[i]; @@ -2429,14 +2444,20 @@ ixgbe_get_buf(struct rx_ring *rxr, int i return (ENOBUFS); } - /* needed in any case so prealocate since this one will fail for sure */ - mp = MCLGETI(NULL, M_DONTWAIT, NULL, sc->rx_mbuf_sz); - if (!mp) + MGETHDR(mp, M_DONTWAIT, MT_DATA); + if (mp == NULL) return (ENOBUFS); - mp->m_len = mp->m_pkthdr.len = sc->rx_mbuf_sz; - if (sc->max_frame_size <= (sc->rx_mbuf_sz - ETHER_ALIGN)) - m_adj(mp, ETHER_ALIGN); + mcl = pool_get(ix_mcl_pool, PR_NOWAIT); + if (mcl == NULL) { + m_freem(mp); + return (ENOBUFS); + } + MEXTADD(mp, mcl, IX_MCLBYTES + ETHER_ALIGN, M_EXTWR, + m_extfree_pool, ix_mcl_pool); + + mp->m_len = mp->m_pkthdr.len = IX_MCLBYTES + ETHER_ALIGN; + m_adj(mp, ETHER_ALIGN); error = bus_dmamap_load_mbuf(rxr->rxdma.dma_tag, rxbuf->map, mp, BUS_DMA_NOWAIT);