ohci-mem.c (4126B)
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 27static 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 37static 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 65static 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 */ 76static inline struct td * 77dma_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 ... */ 89static struct td * 90td_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 110static void 111td_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 ... */ 133static struct ed * 134ed_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 152static void 153ed_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