In USB land there is a lot of freelists.  Every HC driver has one
freelist per type of descriptor and the memory allocator used to
populate these lists, usb_allocmem(), is a wrapper around
bus_dma{mem,map}* that uses two more lists.

I don't see the point of having per-softc lists, but maybe somebody
has a better understanding of this.

I'd like to remove these lists and use usb_allocmem() directly.  The
first reason for this change is to reduce the number of layers on top
of the memory allocator to track memleaks.  Since I need to change the
way ehci(4)'s descriptor are allocated when a transfer is submitted,
this would definitively help.

This diff only removes the freelists for the descriptors used by
control, interrupt and bulk transfers.  Isochronous will follow.

Ok?

Index: ehci.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/ehci.c,v
retrieving revision 1.151
diff -u -p -r1.151 ehci.c
--- ehci.c      4 May 2014 14:42:36 -0000       1.151
+++ ehci.c      4 May 2014 14:44:08 -0000
@@ -2354,83 +2354,43 @@ struct ehci_soft_qh *
 ehci_alloc_sqh(struct ehci_softc *sc)
 {
        struct ehci_soft_qh *sqh;
-       usbd_status err;
-       int i, offs;
        struct usb_dma dma;
 
-       if (sc->sc_freeqhs == NULL) {
-               DPRINTFN(2, ("ehci_alloc_sqh: allocating chunk\n"));
-               err = usb_allocmem(&sc->sc_bus, EHCI_SQH_SIZE * EHCI_SQH_CHUNK,
-                   EHCI_PAGE_SIZE, &dma);
-#ifdef EHCI_DEBUG
-               if (err)
-                       printf("ehci_alloc_sqh: usb_allocmem()=%d\n", err);
-#endif
-               if (err)
-                       return (NULL);
-               for(i = 0; i < EHCI_SQH_CHUNK; i++) {
-                       offs = i * EHCI_SQH_SIZE;
-                       sqh = KERNADDR(&dma, offs);
-                       sqh->physaddr = DMAADDR(&dma, offs);
-                       sqh->dma = dma;
-                       sqh->offs = offs;
-                       sqh->next = sc->sc_freeqhs;
-                       sc->sc_freeqhs = sqh;
-               }
-       }
-       sqh = sc->sc_freeqhs;
-       sc->sc_freeqhs = sqh->next;
-       memset(&sqh->qh, 0, sizeof(struct ehci_qh));
+       if (usb_allocmem(&sc->sc_bus, sizeof(*sqh), EHCI_QH_ALIGN, &dma))
+               return (NULL);
+
+       sqh = KERNADDR(&dma, 0);
+       sqh->physaddr = DMAADDR(&dma, 0);
+       sqh->dma = dma;
+       sqh->offs = 0;
        sqh->next = NULL;
        sqh->prev = NULL;
+       memset(&sqh->qh, 0, sizeof(struct ehci_qh));
+
        return (sqh);
 }
 
 void
 ehci_free_sqh(struct ehci_softc *sc, struct ehci_soft_qh *sqh)
 {
-       sqh->next = sc->sc_freeqhs;
-       sc->sc_freeqhs = sqh;
+       usb_freemem(&sc->sc_bus, &sqh->dma);
 }
 
 struct ehci_soft_qtd *
 ehci_alloc_sqtd(struct ehci_softc *sc)
 {
        struct ehci_soft_qtd *sqtd;
-       usbd_status err;
-       int i, offs;
        struct usb_dma dma;
-       int s;
 
-       if (sc->sc_freeqtds == NULL) {
-               DPRINTFN(2, ("ehci_alloc_sqtd: allocating chunk\n"));
-               err = usb_allocmem(&sc->sc_bus, EHCI_SQTD_SIZE*EHCI_SQTD_CHUNK,
-                   EHCI_PAGE_SIZE, &dma);
-#ifdef EHCI_DEBUG
-               if (err)
-                       printf("ehci_alloc_sqtd: usb_allocmem()=%d\n", err);
-#endif
-               if (err)
-                       return (NULL);
-               s = splusb();
-               for(i = 0; i < EHCI_SQTD_CHUNK; i++) {
-                       offs = i * EHCI_SQTD_SIZE;
-                       sqtd = KERNADDR(&dma, offs);
-                       sqtd->physaddr = DMAADDR(&dma, offs);
-                       sqtd->dma = dma;
-                       sqtd->offs = offs;
-                       sqtd->nextqtd = sc->sc_freeqtds;
-                       sc->sc_freeqtds = sqtd;
-               }
-               splx(s);
-       }
-
-       s = splusb();
-       sqtd = sc->sc_freeqtds;
-       sc->sc_freeqtds = sqtd->nextqtd;
-       memset(&sqtd->qtd, 0, sizeof(struct ehci_qtd));
+       if (usb_allocmem(&sc->sc_bus, sizeof(*sqtd), EHCI_QTD_ALIGN, &dma))
+               return (NULL);
+
+       sqtd = KERNADDR(&dma, 0);
+       sqtd->physaddr = DMAADDR(&dma, 0);
+       sqtd->dma = dma;
+       sqtd->offs = 0;
        sqtd->nextqtd = NULL;
-       splx(s);
+       memset(&sqtd->qtd, 0, sizeof(struct ehci_qtd));
 
        return (sqtd);
 }
@@ -2438,12 +2398,7 @@ ehci_alloc_sqtd(struct ehci_softc *sc)
 void
 ehci_free_sqtd(struct ehci_softc *sc, struct ehci_soft_qtd *sqtd)
 {
-       int s;
-
-       s = splusb();
-       sqtd->nextqtd = sc->sc_freeqtds;
-       sc->sc_freeqtds = sqtd;
-       splx(s);
+       usb_freemem(&sc->sc_bus, &sqtd->dma);
 }
 
 usbd_status
Index: ehcivar.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/ehcivar.h,v
retrieving revision 1.31
diff -u -p -r1.31 ehcivar.h
--- ehcivar.h   29 Apr 2014 12:45:29 -0000      1.31
+++ ehcivar.h   4 May 2014 14:44:08 -0000
@@ -39,8 +39,6 @@ struct ehci_soft_qtd {
        LIST_ENTRY(ehci_soft_qtd) hnext;
        u_int16_t len;
 };
-#define EHCI_SQTD_SIZE ((sizeof (struct ehci_soft_qtd) + EHCI_QTD_ALIGN - 1) / 
EHCI_QTD_ALIGN * EHCI_QTD_ALIGN)
-#define EHCI_SQTD_CHUNK (EHCI_PAGE_SIZE / EHCI_SQTD_SIZE)
 
 struct ehci_soft_qh {
        struct ehci_qh qh;
@@ -52,8 +50,6 @@ struct ehci_soft_qh {
        int offs;                       /* QH's offset in struct usb_dma */
        int islot;
 };
-#define EHCI_SQH_SIZE ((sizeof (struct ehci_soft_qh) + EHCI_QH_ALIGN - 1) / 
EHCI_QH_ALIGN * EHCI_QH_ALIGN)
-#define EHCI_SQH_CHUNK (EHCI_PAGE_SIZE / EHCI_SQH_SIZE)
 
 struct ehci_soft_itd {
        struct ehci_itd itd;
@@ -107,8 +103,6 @@ struct ehci_soft_islot {
 #define EHCI_HASH_SIZE 128
 #define EHCI_COMPANION_MAX 8
 
-#define EHCI_FREE_LIST_INTERVAL 100
-
 struct ehci_softc {
        struct usbd_bus sc_bus;         /* base device */
        bus_space_tag_t iot;
@@ -134,8 +128,6 @@ struct ehci_softc {
 
        TAILQ_HEAD(, ehci_xfer) sc_intrhead;
 
-       struct ehci_soft_qh *sc_freeqhs;
-       struct ehci_soft_qtd *sc_freeqtds;
        LIST_HEAD(sc_freeitds, ehci_soft_itd) sc_freeitds;
 
        int sc_noport;
Index: ohci.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/ohci.c,v
retrieving revision 1.128
diff -u -p -r1.128 ohci.c
--- ohci.c      4 May 2014 14:42:36 -0000       1.128
+++ ohci.c      4 May 2014 14:44:09 -0000
@@ -98,6 +98,7 @@ usbd_status   ohci_device_request(struct u
 void           ohci_add_ed(struct ohci_soft_ed *, struct ohci_soft_ed *);
 void           ohci_rem_ed(struct ohci_soft_ed *, struct ohci_soft_ed *);
 void           ohci_hash_add_td(struct ohci_softc *, struct ohci_soft_td *);
+void           ohci_hash_rem_td(struct ohci_softc *, struct ohci_soft_td *);
 struct ohci_soft_td *ohci_hash_find_td(struct ohci_softc *, ohci_physaddr_t);
 void           ohci_hash_add_itd(struct ohci_softc *, struct ohci_soft_itd *);
 void           ohci_hash_rem_itd(struct ohci_softc *, struct ohci_soft_itd *);
@@ -405,70 +406,44 @@ struct ohci_soft_ed *
 ohci_alloc_sed(struct ohci_softc *sc)
 {
        struct ohci_soft_ed *sed;
-       usbd_status err;
-       int i, offs;
        struct usb_dma dma;
 
-       if (sc->sc_freeeds == NULL) {
-               DPRINTFN(2, ("ohci_alloc_sed: allocating chunk\n"));
-               err = usb_allocmem(&sc->sc_bus, OHCI_SED_SIZE * OHCI_SED_CHUNK,
-                         OHCI_ED_ALIGN, &dma);
-               if (err)
-                       return (0);
-               for(i = 0; i < OHCI_SED_CHUNK; i++) {
-                       offs = i * OHCI_SED_SIZE;
-                       sed = KERNADDR(&dma, offs);
-                       sed->physaddr = DMAADDR(&dma, offs);
-                       sed->next = sc->sc_freeeds;
-                       sc->sc_freeeds = sed;
-               }
-       }
-       sed = sc->sc_freeeds;
-       sc->sc_freeeds = sed->next;
-       memset(&sed->ed, 0, sizeof(struct ohci_ed));
+       if (usb_allocmem(&sc->sc_bus, sizeof(*sed), OHCI_ED_ALIGN, &dma))
+               return (NULL);
+
+       sed = KERNADDR(&dma, 0);
+       sed->physaddr = DMAADDR(&dma, 0);
+       sed->dma = dma;
        sed->next = NULL;
+       memset(&sed->ed, 0, sizeof(struct ohci_ed));
+
        return (sed);
 }
 
 void
 ohci_free_sed(struct ohci_softc *sc, struct ohci_soft_ed *sed)
 {
-       sed->next = sc->sc_freeeds;
-       sc->sc_freeeds = sed;
+       usb_freemem(&sc->sc_bus, &sed->dma);
 }
 
 struct ohci_soft_td *
 ohci_alloc_std(struct ohci_softc *sc)
 {
        struct ohci_soft_td *std;
-       usbd_status err;
-       int i, offs;
        struct usb_dma dma;
        int s;
 
-       if (sc->sc_freetds == NULL) {
-               DPRINTFN(2, ("ohci_alloc_std: allocating chunk\n"));
-               err = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE * OHCI_STD_CHUNK,
-                         OHCI_TD_ALIGN, &dma);
-               if (err)
-                       return (NULL);
-               s = splusb();
-               for(i = 0; i < OHCI_STD_CHUNK; i++) {
-                       offs = i * OHCI_STD_SIZE;
-                       std = KERNADDR(&dma, offs);
-                       std->physaddr = DMAADDR(&dma, offs);
-                       std->nexttd = sc->sc_freetds;
-                       sc->sc_freetds = std;
-               }
-               splx(s);
-       }
+       if (usb_allocmem(&sc->sc_bus, sizeof(*std), OHCI_TD_ALIGN, &dma))
+               return (NULL);
 
-       s = splusb();
-       std = sc->sc_freetds;
-       sc->sc_freetds = std->nexttd;
-       memset(&std->td, 0, sizeof(struct ohci_td));
+       std = KERNADDR(&dma, 0);
+       std->physaddr = DMAADDR(&dma, 0);
+       std->dma = dma;
        std->nexttd = NULL;
        std->xfer = NULL;
+       memset(&std->td, 0, sizeof(struct ohci_td));
+
+       s = splusb();
        ohci_hash_add_td(sc, std);
        splx(s);
 
@@ -481,10 +456,10 @@ ohci_free_std(struct ohci_softc *sc, str
        int s;
 
        s = splusb();
-       LIST_REMOVE(std, hnext);
-       std->nexttd = sc->sc_freetds;
-       sc->sc_freetds = std;
+       ohci_hash_rem_td(sc, std);
        splx(s);
+
+       usb_freemem(&sc->sc_bus, &std->dma);
 }
 
 usbd_status
@@ -1758,6 +1733,14 @@ ohci_hash_add_td(struct ohci_softc *sc, 
        SPLUSBCHECK;
 
        LIST_INSERT_HEAD(&sc->sc_hash_tds[h], std, hnext);
+}
+
+void
+ohci_hash_rem_td(struct ohci_softc *sc, struct ohci_soft_td *std)
+{
+       SPLUSBCHECK;
+
+       LIST_REMOVE(std, hnext);
 }
 
 struct ohci_soft_td *
Index: ohcivar.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/ohcivar.h,v
retrieving revision 1.36
diff -u -p -r1.36 ohcivar.h
--- ohcivar.h   29 Apr 2014 21:51:18 -0000      1.36
+++ ohcivar.h   4 May 2014 14:44:09 -0000
@@ -36,16 +36,15 @@ struct ohci_soft_ed {
        struct ohci_ed ed;
        struct ohci_soft_ed *next;
        ohci_physaddr_t physaddr;
+       struct usb_dma dma;
 };
-#define OHCI_SED_SIZE ((sizeof (struct ohci_soft_ed) + OHCI_ED_ALIGN - 1) / 
OHCI_ED_ALIGN * OHCI_ED_ALIGN)
-#define OHCI_SED_CHUNK 128
-
 
 struct ohci_soft_td {
        struct ohci_td td;
        struct ohci_soft_td *nexttd; /* mirrors nexttd in TD */
        struct ohci_soft_td *dnext; /* next in done list */
        ohci_physaddr_t physaddr;
+       struct usb_dma dma;
        LIST_ENTRY(ohci_soft_td) hnext;
        struct usbd_xfer *xfer;
        u_int16_t len;
@@ -53,9 +52,6 @@ struct ohci_soft_td {
 #define OHCI_CALL_DONE 0x0001
 #define OHCI_ADD_LEN   0x0002
 };
-#define OHCI_STD_SIZE ((sizeof (struct ohci_soft_td) + OHCI_TD_ALIGN - 1) / 
OHCI_TD_ALIGN * OHCI_TD_ALIGN)
-#define OHCI_STD_CHUNK 128
-
 
 struct ohci_soft_itd {
        struct ohci_itd itd;
@@ -101,8 +97,6 @@ struct ohci_softc {
 
        char sc_softwake;
 
-       struct ohci_soft_ed *sc_freeeds;
-       struct ohci_soft_td *sc_freetds;
        struct ohci_soft_itd *sc_freeitds;
 
        struct usbd_xfer *sc_intrxfer;
Index: uhci.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/uhci.c,v
retrieving revision 1.114
diff -u -p -r1.114 uhci.c
--- uhci.c      4 May 2014 14:42:36 -0000       1.114
+++ uhci.c      4 May 2014 14:44:11 -0000
@@ -1471,33 +1471,16 @@ struct uhci_soft_td *
 uhci_alloc_std(struct uhci_softc *sc)
 {
        struct uhci_soft_td *std;
-       usbd_status err;
-       int i, offs;
        struct usb_dma dma;
-       int s;
 
-       if (sc->sc_freetds == NULL) {
-               DPRINTFN(2,("uhci_alloc_std: allocating chunk\n"));
-               err = usb_allocmem(&sc->sc_bus, UHCI_STD_SIZE * UHCI_STD_CHUNK,
-                         UHCI_TD_ALIGN, &dma);
-               if (err)
-                       return (0);
-               s = splusb();
-               for(i = 0; i < UHCI_STD_CHUNK; i++) {
-                       offs = i * UHCI_STD_SIZE;
-                       std = KERNADDR(&dma, offs);
-                       std->physaddr = DMAADDR(&dma, offs);
-                       std->link.std = sc->sc_freetds;
-                       sc->sc_freetds = std;
-               }
-               splx(s);
-       }
+       if (usb_allocmem(&sc->sc_bus, sizeof(*std), UHCI_TD_ALIGN, &dma))
+               return (NULL);
 
-       s = splusb();
-       std = sc->sc_freetds;
-       sc->sc_freetds = std->link.std;
+       std = KERNADDR(&dma, 0);
+       std->physaddr = DMAADDR(&dma, 0);
+       std->dma = dma;
+       std->link.std = NULL;
        memset(&std->td, 0, sizeof(struct uhci_td));
-       splx(s);
 
        return (std);
 }
@@ -1505,8 +1488,6 @@ uhci_alloc_std(struct uhci_softc *sc)
 void
 uhci_free_std(struct uhci_softc *sc, struct uhci_soft_td *std)
 {
-       int s;
-
 #ifdef DIAGNOSTIC
 #define TD_IS_FREE 0x12345678
        if (letoh32(std->td.td_token) == TD_IS_FREE) {
@@ -1516,45 +1497,31 @@ uhci_free_std(struct uhci_softc *sc, str
        std->td.td_token = htole32(TD_IS_FREE);
 #endif
 
-       s = splusb();
-       std->link.std = sc->sc_freetds;
-       sc->sc_freetds = std;
-       splx(s);
+       usb_freemem(&sc->sc_bus, &std->dma);
 }
 
 struct uhci_soft_qh *
 uhci_alloc_sqh(struct uhci_softc *sc)
 {
        struct uhci_soft_qh *sqh;
-       usbd_status err;
-       int i, offs;
        struct usb_dma dma;
 
-       if (sc->sc_freeqhs == NULL) {
-               DPRINTFN(2, ("uhci_alloc_sqh: allocating chunk\n"));
-               err = usb_allocmem(&sc->sc_bus, UHCI_SQH_SIZE * UHCI_SQH_CHUNK,
-                         UHCI_QH_ALIGN, &dma);
-               if (err)
-                       return (0);
-               for(i = 0; i < UHCI_SQH_CHUNK; i++) {
-                       offs = i * UHCI_SQH_SIZE;
-                       sqh = KERNADDR(&dma, offs);
-                       sqh->physaddr = DMAADDR(&dma, offs);
-                       sqh->hlink = sc->sc_freeqhs;
-                       sc->sc_freeqhs = sqh;
-               }
-       }
-       sqh = sc->sc_freeqhs;
-       sc->sc_freeqhs = sqh->hlink;
+       if (usb_allocmem(&sc->sc_bus, sizeof(*sqh), UHCI_QH_ALIGN, &dma))
+               return (NULL);
+
+       sqh = KERNADDR(&dma, 0);
+       sqh->physaddr = DMAADDR(&dma, 0);
+       sqh->dma = dma;
+       sqh->hlink = NULL;
        memset(&sqh->qh, 0, sizeof(struct uhci_qh));
+
        return (sqh);
 }
 
 void
 uhci_free_sqh(struct uhci_softc *sc, struct uhci_soft_qh *sqh)
 {
-       sqh->hlink = sc->sc_freeqhs;
-       sc->sc_freeqhs = sqh;
+       usb_freemem(&sc->sc_bus, &sqh->dma);
 }
 
 void
Index: uhcivar.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/uhcivar.h,v
retrieving revision 1.31
diff -u -p -r1.31 uhcivar.h
--- uhcivar.h   29 Apr 2014 21:51:18 -0000      1.31
+++ uhcivar.h   4 May 2014 14:44:11 -0000
@@ -81,15 +81,8 @@ struct uhci_soft_td {
        struct uhci_td td;              /* The real TD, must be first */
        uhci_soft_td_qh_t link;         /* soft version of the td_link field */
        uhci_physaddr_t physaddr;       /* TD's physical address. */
+       struct usb_dma dma;
 };
-/*
- * Make the size such that it is a multiple of UHCI_TD_ALIGN.  This way
- * we can pack a number of soft TD together and have the real TD well
- * aligned.
- * NOTE: Minimum size is 32 bytes.
- */
-#define UHCI_STD_SIZE ((sizeof (struct uhci_soft_td) + UHCI_TD_ALIGN - 1) / 
UHCI_TD_ALIGN * UHCI_TD_ALIGN)
-#define UHCI_STD_CHUNK 128 /*(PAGE_SIZE / UHCI_TD_SIZE)*/
 
 /*
  * Extra information that we need for a QH.
@@ -99,11 +92,9 @@ struct uhci_soft_qh {
        struct uhci_soft_qh *hlink;     /* soft version of qh_hlink */
        struct uhci_soft_td *elink;     /* soft version of qh_elink */
        uhci_physaddr_t physaddr;       /* QH's physical address. */
+       struct usb_dma dma;
        int pos;                        /* Timeslot position */
 };
-/* See comment about UHCI_STD_SIZE. */
-#define UHCI_SQH_SIZE ((sizeof (struct uhci_soft_qh) + UHCI_QH_ALIGN - 1) / 
UHCI_QH_ALIGN * UHCI_QH_ALIGN)
-#define UHCI_SQH_CHUNK 128 /*(PAGE_SIZE / UHCI_QH_SIZE)*/
 
 /*
  * Information about an entry in the virtual frame list.
@@ -134,9 +125,6 @@ struct uhci_softc {
        struct uhci_soft_qh *sc_bulk_end; /* last bulk transfer */
        struct uhci_soft_qh *sc_last_qh; /* dummy QH at the end */
        u_int32_t sc_loops;             /* number of QHs that wants looping */
-
-       struct uhci_soft_td *sc_freetds; /* TD free list */
-       struct uhci_soft_qh *sc_freeqhs; /* QH free list */
 
        u_int8_t sc_conf;               /* device configuration */
 

Reply via email to