Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Copyright (c) 2001 by David Brownell | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify it | |
5 | * under the terms of the GNU General Public License as published by the | |
6 | * Free Software Foundation; either version 2 of the License, or (at your | |
7 | * option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, but | |
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
11 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 | * for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with this program; if not, write to the Free Software Foundation, | |
16 | * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
17 | */ | |
18 | ||
19 | /* this file is part of ehci-hcd.c */ | |
20 | ||
21 | /*-------------------------------------------------------------------------*/ | |
22 | ||
23 | /* | |
24 | * There's basically three types of memory: | |
25 | * - data used only by the HCD ... kmalloc is fine | |
26 | * - async and periodic schedules, shared by HC and HCD ... these | |
27 | * need to use dma_pool or dma_alloc_coherent | |
28 | * - driver buffers, read/written by HC ... single shot DMA mapped | |
29 | * | |
30 | * There's also PCI "register" data, which is memory mapped. | |
31 | * No memory seen by this driver is pageable. | |
32 | */ | |
33 | ||
34 | /*-------------------------------------------------------------------------*/ | |
35 | ||
36 | /* Allocate the key transfer structures from the previously allocated pool */ | |
37 | ||
38 | static inline void ehci_qtd_init (struct ehci_qtd *qtd, dma_addr_t dma) | |
39 | { | |
40 | memset (qtd, 0, sizeof *qtd); | |
41 | qtd->qtd_dma = dma; | |
42 | qtd->hw_token = cpu_to_le32 (QTD_STS_HALT); | |
43 | qtd->hw_next = EHCI_LIST_END; | |
44 | qtd->hw_alt_next = EHCI_LIST_END; | |
45 | INIT_LIST_HEAD (&qtd->qtd_list); | |
46 | } | |
47 | ||
55016f10 | 48 | static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, gfp_t flags) |
1da177e4 LT |
49 | { |
50 | struct ehci_qtd *qtd; | |
51 | dma_addr_t dma; | |
52 | ||
53 | qtd = dma_pool_alloc (ehci->qtd_pool, flags, &dma); | |
54 | if (qtd != NULL) { | |
55 | ehci_qtd_init (qtd, dma); | |
56 | } | |
57 | return qtd; | |
58 | } | |
59 | ||
60 | static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd) | |
61 | { | |
62 | dma_pool_free (ehci->qtd_pool, qtd, qtd->qtd_dma); | |
63 | } | |
64 | ||
65 | ||
66 | static void qh_destroy (struct kref *kref) | |
67 | { | |
68 | struct ehci_qh *qh = container_of(kref, struct ehci_qh, kref); | |
69 | struct ehci_hcd *ehci = qh->ehci; | |
70 | ||
71 | /* clean qtds first, and know this is not linked */ | |
72 | if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) { | |
73 | ehci_dbg (ehci, "unused qh not empty!\n"); | |
74 | BUG (); | |
75 | } | |
76 | if (qh->dummy) | |
77 | ehci_qtd_free (ehci, qh->dummy); | |
1da177e4 LT |
78 | dma_pool_free (ehci->qh_pool, qh, qh->qh_dma); |
79 | } | |
80 | ||
55016f10 | 81 | static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags) |
1da177e4 LT |
82 | { |
83 | struct ehci_qh *qh; | |
84 | dma_addr_t dma; | |
85 | ||
86 | qh = (struct ehci_qh *) | |
87 | dma_pool_alloc (ehci->qh_pool, flags, &dma); | |
88 | if (!qh) | |
89 | return qh; | |
90 | ||
91 | memset (qh, 0, sizeof *qh); | |
92 | kref_init(&qh->kref); | |
93 | qh->ehci = ehci; | |
94 | qh->qh_dma = dma; | |
95 | // INIT_LIST_HEAD (&qh->qh_list); | |
96 | INIT_LIST_HEAD (&qh->qtd_list); | |
97 | ||
98 | /* dummy td enables safe urb queuing */ | |
99 | qh->dummy = ehci_qtd_alloc (ehci, flags); | |
100 | if (qh->dummy == NULL) { | |
101 | ehci_dbg (ehci, "no dummy td\n"); | |
102 | dma_pool_free (ehci->qh_pool, qh, qh->qh_dma); | |
103 | qh = NULL; | |
104 | } | |
105 | return qh; | |
106 | } | |
107 | ||
108 | /* to share a qh (cpu threads, or hc) */ | |
109 | static inline struct ehci_qh *qh_get (struct ehci_qh *qh) | |
110 | { | |
111 | kref_get(&qh->kref); | |
112 | return qh; | |
113 | } | |
114 | ||
115 | static inline void qh_put (struct ehci_qh *qh) | |
116 | { | |
117 | kref_put(&qh->kref, qh_destroy); | |
118 | } | |
119 | ||
120 | /*-------------------------------------------------------------------------*/ | |
121 | ||
122 | /* The queue heads and transfer descriptors are managed from pools tied | |
123 | * to each of the "per device" structures. | |
124 | * This is the initialisation and cleanup code. | |
125 | */ | |
126 | ||
127 | static void ehci_mem_cleanup (struct ehci_hcd *ehci) | |
128 | { | |
129 | if (ehci->async) | |
130 | qh_put (ehci->async); | |
131 | ehci->async = NULL; | |
132 | ||
133 | /* DMA consistent memory and pools */ | |
134 | if (ehci->qtd_pool) | |
135 | dma_pool_destroy (ehci->qtd_pool); | |
136 | ehci->qtd_pool = NULL; | |
137 | ||
138 | if (ehci->qh_pool) { | |
139 | dma_pool_destroy (ehci->qh_pool); | |
140 | ehci->qh_pool = NULL; | |
141 | } | |
142 | ||
143 | if (ehci->itd_pool) | |
144 | dma_pool_destroy (ehci->itd_pool); | |
145 | ehci->itd_pool = NULL; | |
146 | ||
147 | if (ehci->sitd_pool) | |
148 | dma_pool_destroy (ehci->sitd_pool); | |
149 | ehci->sitd_pool = NULL; | |
150 | ||
151 | if (ehci->periodic) | |
152 | dma_free_coherent (ehci_to_hcd(ehci)->self.controller, | |
153 | ehci->periodic_size * sizeof (u32), | |
154 | ehci->periodic, ehci->periodic_dma); | |
155 | ehci->periodic = NULL; | |
156 | ||
157 | /* shadow periodic table */ | |
1bc3c9e1 | 158 | kfree(ehci->pshadow); |
1da177e4 LT |
159 | ehci->pshadow = NULL; |
160 | } | |
161 | ||
162 | /* remember to add cleanup code (above) if you add anything here */ | |
55016f10 | 163 | static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) |
1da177e4 LT |
164 | { |
165 | int i; | |
166 | ||
167 | /* QTDs for control/bulk/intr transfers */ | |
168 | ehci->qtd_pool = dma_pool_create ("ehci_qtd", | |
169 | ehci_to_hcd(ehci)->self.controller, | |
170 | sizeof (struct ehci_qtd), | |
171 | 32 /* byte alignment (for hw parts) */, | |
172 | 4096 /* can't cross 4K */); | |
173 | if (!ehci->qtd_pool) { | |
174 | goto fail; | |
175 | } | |
176 | ||
177 | /* QHs for control/bulk/intr transfers */ | |
178 | ehci->qh_pool = dma_pool_create ("ehci_qh", | |
179 | ehci_to_hcd(ehci)->self.controller, | |
180 | sizeof (struct ehci_qh), | |
181 | 32 /* byte alignment (for hw parts) */, | |
182 | 4096 /* can't cross 4K */); | |
183 | if (!ehci->qh_pool) { | |
184 | goto fail; | |
185 | } | |
186 | ehci->async = ehci_qh_alloc (ehci, flags); | |
187 | if (!ehci->async) { | |
188 | goto fail; | |
189 | } | |
190 | ||
191 | /* ITD for high speed ISO transfers */ | |
192 | ehci->itd_pool = dma_pool_create ("ehci_itd", | |
193 | ehci_to_hcd(ehci)->self.controller, | |
194 | sizeof (struct ehci_itd), | |
195 | 32 /* byte alignment (for hw parts) */, | |
196 | 4096 /* can't cross 4K */); | |
197 | if (!ehci->itd_pool) { | |
198 | goto fail; | |
199 | } | |
200 | ||
201 | /* SITD for full/low speed split ISO transfers */ | |
202 | ehci->sitd_pool = dma_pool_create ("ehci_sitd", | |
203 | ehci_to_hcd(ehci)->self.controller, | |
204 | sizeof (struct ehci_sitd), | |
205 | 32 /* byte alignment (for hw parts) */, | |
206 | 4096 /* can't cross 4K */); | |
207 | if (!ehci->sitd_pool) { | |
208 | goto fail; | |
209 | } | |
210 | ||
211 | /* Hardware periodic table */ | |
212 | ehci->periodic = (__le32 *) | |
213 | dma_alloc_coherent (ehci_to_hcd(ehci)->self.controller, | |
214 | ehci->periodic_size * sizeof(__le32), | |
215 | &ehci->periodic_dma, 0); | |
216 | if (ehci->periodic == NULL) { | |
217 | goto fail; | |
218 | } | |
219 | for (i = 0; i < ehci->periodic_size; i++) | |
220 | ehci->periodic [i] = EHCI_LIST_END; | |
221 | ||
222 | /* software shadow of hardware table */ | |
223 | ehci->pshadow = kmalloc (ehci->periodic_size * sizeof (void *), flags); | |
224 | if (ehci->pshadow == NULL) { | |
225 | goto fail; | |
226 | } | |
227 | memset (ehci->pshadow, 0, ehci->periodic_size * sizeof (void *)); | |
228 | ||
229 | return 0; | |
230 | ||
231 | fail: | |
232 | ehci_dbg (ehci, "couldn't init memory\n"); | |
233 | ehci_mem_cleanup (ehci); | |
234 | return -ENOMEM; | |
235 | } |