| 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 (list: &ohci->pending); | 
|---|
| 32 | INIT_LIST_HEAD(list: &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 (name: "ohci_td", | 
|---|
| 47 | dev: ohci_to_hcd(ohci)->self.controller, | 
|---|
| 48 | size: sizeof (struct td), | 
|---|
| 49 | align: 32 /* byte alignment */, | 
|---|
| 50 | boundary: 0 /* no page-crossing issues */); | 
|---|
| 51 | if (!ohci->td_cache) | 
|---|
| 52 | return -ENOMEM; | 
|---|
| 53 | ohci->ed_cache = dma_pool_create (name: "ohci_ed", | 
|---|
| 54 | dev: ohci_to_hcd(ohci)->self.controller, | 
|---|
| 55 | size: sizeof (struct ed), | 
|---|
| 56 | align: 16 /* byte alignment */, | 
|---|
| 57 | boundary: 0 /* no page-crossing issues */); | 
|---|
| 58 | if (!ohci->ed_cache) { | 
|---|
| 59 | dma_pool_destroy (pool: 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(pool: ohci->td_cache); | 
|---|
| 68 | ohci->td_cache = NULL; | 
|---|
| 69 | dma_pool_destroy(pool: 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(ohci: hc); | 
|---|
| 95 |  | 
|---|
| 96 | if (hcd->localmem_pool) | 
|---|
| 97 | td = gen_pool_dma_zalloc_align(pool: hcd->localmem_pool, | 
|---|
| 98 | size: sizeof(*td), dma: &dma, align: 32); | 
|---|
| 99 | else | 
|---|
| 100 | td = dma_pool_zalloc(pool: hc->td_cache, mem_flags, handle: &dma); | 
|---|
| 101 | if (td) { | 
|---|
| 102 | /* in case hc fetches it, make it look dead */ | 
|---|
| 103 | td->hwNextTD = cpu_to_hc32 (ohci: hc, x: 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(ohci: 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(ohci: 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(pool: hcd->localmem_pool, addr: (unsigned long)td, | 
|---|
| 125 | size: sizeof(*td)); | 
|---|
| 126 | else | 
|---|
| 127 | dma_pool_free(pool: hc->td_cache, vaddr: td, addr: 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(ohci: hc); | 
|---|
| 139 |  | 
|---|
| 140 | if (hcd->localmem_pool) | 
|---|
| 141 | ed = gen_pool_dma_zalloc_align(pool: hcd->localmem_pool, | 
|---|
| 142 | size: sizeof(*ed), dma: &dma, align: 16); | 
|---|
| 143 | else | 
|---|
| 144 | ed = dma_pool_zalloc(pool: hc->ed_cache, mem_flags, handle: &dma); | 
|---|
| 145 | if (ed) { | 
|---|
| 146 | INIT_LIST_HEAD (list: &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(ohci: hc); | 
|---|
| 156 |  | 
|---|
| 157 | if (hcd->localmem_pool) | 
|---|
| 158 | gen_pool_free(pool: hcd->localmem_pool, addr: (unsigned long)ed, | 
|---|
| 159 | size: sizeof(*ed)); | 
|---|
| 160 | else | 
|---|
| 161 | dma_pool_free(pool: hc->ed_cache, vaddr: ed, addr: ed->dma); | 
|---|
| 162 | } | 
|---|
| 163 |  | 
|---|
| 164 |  | 
|---|