root/drivers/usb/host/ohci-mem.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ohci_hcd_init
  2. ohci_mem_init
  3. ohci_mem_cleanup
  4. dma_to_td
  5. td_alloc
  6. td_free
  7. ed_alloc
  8. ed_free

   1 // SPDX-License-Identifier: GPL-1.0+
   2 /*
   3  * OHCI HCD (Host Controller Driver) for USB.
   4  *
   5  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
   6  * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
   7  *
   8  * This file is licenced under the GPL.
   9  */
  10 
  11 /*-------------------------------------------------------------------------*/
  12 
  13 /*
  14  * OHCI deals with three types of memory:
  15  *      - data used only by the HCD ... kmalloc is fine
  16  *      - async and periodic schedules, shared by HC and HCD ... these
  17  *        need to use dma_pool or dma_alloc_coherent
  18  *      - driver buffers, read/written by HC ... the hcd glue or the
  19  *        device driver provides us with dma addresses
  20  *
  21  * There's also "register" data, which is memory mapped.
  22  * No memory seen by this driver (or any HCD) may be paged out.
  23  */
  24 
  25 /*-------------------------------------------------------------------------*/
  26 
  27 static void ohci_hcd_init (struct ohci_hcd *ohci)
  28 {
  29         ohci->next_statechange = jiffies;
  30         spin_lock_init (&ohci->lock);
  31         INIT_LIST_HEAD (&ohci->pending);
  32         INIT_LIST_HEAD(&ohci->eds_in_use);
  33 }
  34 
  35 /*-------------------------------------------------------------------------*/
  36 
  37 static int ohci_mem_init (struct ohci_hcd *ohci)
  38 {
  39         /*
  40          * HCs with local memory allocate from localmem_pool so there's
  41          * no need to create the below dma pools.
  42          */
  43         if (ohci_to_hcd(ohci)->localmem_pool)
  44                 return 0;
  45 
  46         ohci->td_cache = dma_pool_create ("ohci_td",
  47                 ohci_to_hcd(ohci)->self.controller,
  48                 sizeof (struct td),
  49                 32 /* byte alignment */,
  50                 0 /* no page-crossing issues */);
  51         if (!ohci->td_cache)
  52                 return -ENOMEM;
  53         ohci->ed_cache = dma_pool_create ("ohci_ed",
  54                 ohci_to_hcd(ohci)->self.controller,
  55                 sizeof (struct ed),
  56                 16 /* byte alignment */,
  57                 0 /* no page-crossing issues */);
  58         if (!ohci->ed_cache) {
  59                 dma_pool_destroy (ohci->td_cache);
  60                 return -ENOMEM;
  61         }
  62         return 0;
  63 }
  64 
  65 static void ohci_mem_cleanup (struct ohci_hcd *ohci)
  66 {
  67         dma_pool_destroy(ohci->td_cache);
  68         ohci->td_cache = NULL;
  69         dma_pool_destroy(ohci->ed_cache);
  70         ohci->ed_cache = NULL;
  71 }
  72 
  73 /*-------------------------------------------------------------------------*/
  74 
  75 /* ohci "done list" processing needs this mapping */
  76 static inline struct td *
  77 dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
  78 {
  79         struct td *td;
  80 
  81         td_dma &= TD_MASK;
  82         td = hc->td_hash [TD_HASH_FUNC(td_dma)];
  83         while (td && td->td_dma != td_dma)
  84                 td = td->td_hash;
  85         return td;
  86 }
  87 
  88 /* TDs ... */
  89 static struct td *
  90 td_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
  91 {
  92         dma_addr_t      dma;
  93         struct td       *td;
  94         struct usb_hcd  *hcd = ohci_to_hcd(hc);
  95 
  96         if (hcd->localmem_pool)
  97                 td = gen_pool_dma_zalloc_align(hcd->localmem_pool,
  98                                 sizeof(*td), &dma, 32);
  99         else
 100                 td = dma_pool_zalloc(hc->td_cache, mem_flags, &dma);
 101         if (td) {
 102                 /* in case hc fetches it, make it look dead */
 103                 td->hwNextTD = cpu_to_hc32 (hc, dma);
 104                 td->td_dma = dma;
 105                 /* hashed in td_fill */
 106         }
 107         return td;
 108 }
 109 
 110 static void
 111 td_free (struct ohci_hcd *hc, struct td *td)
 112 {
 113         struct td       **prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)];
 114         struct usb_hcd  *hcd = ohci_to_hcd(hc);
 115 
 116         while (*prev && *prev != td)
 117                 prev = &(*prev)->td_hash;
 118         if (*prev)
 119                 *prev = td->td_hash;
 120         else if ((td->hwINFO & cpu_to_hc32(hc, TD_DONE)) != 0)
 121                 ohci_dbg (hc, "no hash for td %p\n", td);
 122 
 123         if (hcd->localmem_pool)
 124                 gen_pool_free(hcd->localmem_pool, (unsigned long)td,
 125                               sizeof(*td));
 126         else
 127                 dma_pool_free(hc->td_cache, td, td->td_dma);
 128 }
 129 
 130 /*-------------------------------------------------------------------------*/
 131 
 132 /* EDs ... */
 133 static struct ed *
 134 ed_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
 135 {
 136         dma_addr_t      dma;
 137         struct ed       *ed;
 138         struct usb_hcd  *hcd = ohci_to_hcd(hc);
 139 
 140         if (hcd->localmem_pool)
 141                 ed = gen_pool_dma_zalloc_align(hcd->localmem_pool,
 142                                 sizeof(*ed), &dma, 16);
 143         else
 144                 ed = dma_pool_zalloc(hc->ed_cache, mem_flags, &dma);
 145         if (ed) {
 146                 INIT_LIST_HEAD (&ed->td_list);
 147                 ed->dma = dma;
 148         }
 149         return ed;
 150 }
 151 
 152 static void
 153 ed_free (struct ohci_hcd *hc, struct ed *ed)
 154 {
 155         struct usb_hcd  *hcd = ohci_to_hcd(hc);
 156 
 157         if (hcd->localmem_pool)
 158                 gen_pool_free(hcd->localmem_pool, (unsigned long)ed,
 159                               sizeof(*ed));
 160         else
 161                 dma_pool_free(hc->ed_cache, ed, ed->dma);
 162 }
 163 

/* [<][>][^][v][top][bottom][index][help] */