Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-1.0+
0002 /*
0003  * OHCI HCD (Host Controller Driver) for USB.
0004  *
0005  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
0006  * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
0007  *
0008  * This file is licenced under the GPL.
0009  */
0010 
0011 /*-------------------------------------------------------------------------*/
0012 
0013 /*
0014  * OHCI deals with three types of memory:
0015  *  - data used only by the HCD ... kmalloc is fine
0016  *  - async and periodic schedules, shared by HC and HCD ... these
0017  *    need to use dma_pool or dma_alloc_coherent
0018  *  - driver buffers, read/written by HC ... the hcd glue or the
0019  *    device driver provides us with dma addresses
0020  *
0021  * There's also "register" data, which is memory mapped.
0022  * No memory seen by this driver (or any HCD) may be paged out.
0023  */
0024 
0025 /*-------------------------------------------------------------------------*/
0026 
0027 static void ohci_hcd_init (struct ohci_hcd *ohci)
0028 {
0029     ohci->next_statechange = jiffies;
0030     spin_lock_init (&ohci->lock);
0031     INIT_LIST_HEAD (&ohci->pending);
0032     INIT_LIST_HEAD(&ohci->eds_in_use);
0033 }
0034 
0035 /*-------------------------------------------------------------------------*/
0036 
0037 static int ohci_mem_init (struct ohci_hcd *ohci)
0038 {
0039     /*
0040      * HCs with local memory allocate from localmem_pool so there's
0041      * no need to create the below dma pools.
0042      */
0043     if (ohci_to_hcd(ohci)->localmem_pool)
0044         return 0;
0045 
0046     ohci->td_cache = dma_pool_create ("ohci_td",
0047         ohci_to_hcd(ohci)->self.controller,
0048         sizeof (struct td),
0049         32 /* byte alignment */,
0050         0 /* no page-crossing issues */);
0051     if (!ohci->td_cache)
0052         return -ENOMEM;
0053     ohci->ed_cache = dma_pool_create ("ohci_ed",
0054         ohci_to_hcd(ohci)->self.controller,
0055         sizeof (struct ed),
0056         16 /* byte alignment */,
0057         0 /* no page-crossing issues */);
0058     if (!ohci->ed_cache) {
0059         dma_pool_destroy (ohci->td_cache);
0060         return -ENOMEM;
0061     }
0062     return 0;
0063 }
0064 
0065 static void ohci_mem_cleanup (struct ohci_hcd *ohci)
0066 {
0067     dma_pool_destroy(ohci->td_cache);
0068     ohci->td_cache = NULL;
0069     dma_pool_destroy(ohci->ed_cache);
0070     ohci->ed_cache = NULL;
0071 }
0072 
0073 /*-------------------------------------------------------------------------*/
0074 
0075 /* ohci "done list" processing needs this mapping */
0076 static inline struct td *
0077 dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
0078 {
0079     struct td *td;
0080 
0081     td_dma &= TD_MASK;
0082     td = hc->td_hash [TD_HASH_FUNC(td_dma)];
0083     while (td && td->td_dma != td_dma)
0084         td = td->td_hash;
0085     return td;
0086 }
0087 
0088 /* TDs ... */
0089 static struct td *
0090 td_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
0091 {
0092     dma_addr_t  dma;
0093     struct td   *td;
0094     struct usb_hcd  *hcd = ohci_to_hcd(hc);
0095 
0096     if (hcd->localmem_pool)
0097         td = gen_pool_dma_zalloc_align(hcd->localmem_pool,
0098                 sizeof(*td), &dma, 32);
0099     else
0100         td = dma_pool_zalloc(hc->td_cache, mem_flags, &dma);
0101     if (td) {
0102         /* in case hc fetches it, make it look dead */
0103         td->hwNextTD = cpu_to_hc32 (hc, dma);
0104         td->td_dma = dma;
0105         /* hashed in td_fill */
0106     }
0107     return td;
0108 }
0109 
0110 static void
0111 td_free (struct ohci_hcd *hc, struct td *td)
0112 {
0113     struct td   **prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)];
0114     struct usb_hcd  *hcd = ohci_to_hcd(hc);
0115 
0116     while (*prev && *prev != td)
0117         prev = &(*prev)->td_hash;
0118     if (*prev)
0119         *prev = td->td_hash;
0120     else if ((td->hwINFO & cpu_to_hc32(hc, TD_DONE)) != 0)
0121         ohci_dbg (hc, "no hash for td %p\n", td);
0122 
0123     if (hcd->localmem_pool)
0124         gen_pool_free(hcd->localmem_pool, (unsigned long)td,
0125                   sizeof(*td));
0126     else
0127         dma_pool_free(hc->td_cache, td, td->td_dma);
0128 }
0129 
0130 /*-------------------------------------------------------------------------*/
0131 
0132 /* EDs ... */
0133 static struct ed *
0134 ed_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
0135 {
0136     dma_addr_t  dma;
0137     struct ed   *ed;
0138     struct usb_hcd  *hcd = ohci_to_hcd(hc);
0139 
0140     if (hcd->localmem_pool)
0141         ed = gen_pool_dma_zalloc_align(hcd->localmem_pool,
0142                 sizeof(*ed), &dma, 16);
0143     else
0144         ed = dma_pool_zalloc(hc->ed_cache, mem_flags, &dma);
0145     if (ed) {
0146         INIT_LIST_HEAD (&ed->td_list);
0147         ed->dma = dma;
0148     }
0149     return ed;
0150 }
0151 
0152 static void
0153 ed_free (struct ohci_hcd *hc, struct ed *ed)
0154 {
0155     struct usb_hcd  *hcd = ohci_to_hcd(hc);
0156 
0157     if (hcd->localmem_pool)
0158         gen_pool_free(hcd->localmem_pool, (unsigned long)ed,
0159                   sizeof(*ed));
0160     else
0161         dma_pool_free(hc->ed_cache, ed, ed->dma);
0162 }
0163