diff options
Diffstat (limited to 'drivers/usb/host/ehci-mem.c')
-rw-r--r-- | drivers/usb/host/ehci-mem.c | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c index a8ba2e1497a4..8816d09903d0 100644 --- a/drivers/usb/host/ehci-mem.c +++ b/drivers/usb/host/ehci-mem.c | |||
@@ -27,7 +27,7 @@ | |||
27 | * need to use dma_pool or dma_alloc_coherent | 27 | * need to use dma_pool or dma_alloc_coherent |
28 | * - driver buffers, read/written by HC ... single shot DMA mapped | 28 | * - driver buffers, read/written by HC ... single shot DMA mapped |
29 | * | 29 | * |
30 | * There's also PCI "register" data, which is memory mapped. | 30 | * There's also "register" data (e.g. PCI or SOC), which is memory mapped. |
31 | * No memory seen by this driver is pageable. | 31 | * No memory seen by this driver is pageable. |
32 | */ | 32 | */ |
33 | 33 | ||
@@ -35,13 +35,14 @@ | |||
35 | 35 | ||
36 | /* Allocate the key transfer structures from the previously allocated pool */ | 36 | /* Allocate the key transfer structures from the previously allocated pool */ |
37 | 37 | ||
38 | static inline void ehci_qtd_init (struct ehci_qtd *qtd, dma_addr_t dma) | 38 | static inline void ehci_qtd_init(struct ehci_hcd *ehci, struct ehci_qtd *qtd, |
39 | dma_addr_t dma) | ||
39 | { | 40 | { |
40 | memset (qtd, 0, sizeof *qtd); | 41 | memset (qtd, 0, sizeof *qtd); |
41 | qtd->qtd_dma = dma; | 42 | qtd->qtd_dma = dma; |
42 | qtd->hw_token = cpu_to_le32 (QTD_STS_HALT); | 43 | qtd->hw_token = cpu_to_le32 (QTD_STS_HALT); |
43 | qtd->hw_next = EHCI_LIST_END; | 44 | qtd->hw_next = EHCI_LIST_END(ehci); |
44 | qtd->hw_alt_next = EHCI_LIST_END; | 45 | qtd->hw_alt_next = EHCI_LIST_END(ehci); |
45 | INIT_LIST_HEAD (&qtd->qtd_list); | 46 | INIT_LIST_HEAD (&qtd->qtd_list); |
46 | } | 47 | } |
47 | 48 | ||
@@ -52,7 +53,7 @@ static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, gfp_t flags) | |||
52 | 53 | ||
53 | qtd = dma_pool_alloc (ehci->qtd_pool, flags, &dma); | 54 | qtd = dma_pool_alloc (ehci->qtd_pool, flags, &dma); |
54 | if (qtd != NULL) { | 55 | if (qtd != NULL) { |
55 | ehci_qtd_init (qtd, dma); | 56 | ehci_qtd_init(ehci, qtd, dma); |
56 | } | 57 | } |
57 | return qtd; | 58 | return qtd; |
58 | } | 59 | } |
@@ -63,9 +64,8 @@ static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd) | |||
63 | } | 64 | } |
64 | 65 | ||
65 | 66 | ||
66 | static void qh_destroy (struct kref *kref) | 67 | static void qh_destroy(struct ehci_qh *qh) |
67 | { | 68 | { |
68 | struct ehci_qh *qh = container_of(kref, struct ehci_qh, kref); | ||
69 | struct ehci_hcd *ehci = qh->ehci; | 69 | struct ehci_hcd *ehci = qh->ehci; |
70 | 70 | ||
71 | /* clean qtds first, and know this is not linked */ | 71 | /* clean qtds first, and know this is not linked */ |
@@ -89,11 +89,14 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags) | |||
89 | return qh; | 89 | return qh; |
90 | 90 | ||
91 | memset (qh, 0, sizeof *qh); | 91 | memset (qh, 0, sizeof *qh); |
92 | kref_init(&qh->kref); | 92 | qh->refcount = 1; |
93 | qh->ehci = ehci; | 93 | qh->ehci = ehci; |
94 | qh->qh_dma = dma; | 94 | qh->qh_dma = dma; |
95 | // INIT_LIST_HEAD (&qh->qh_list); | 95 | // INIT_LIST_HEAD (&qh->qh_list); |
96 | INIT_LIST_HEAD (&qh->qtd_list); | 96 | INIT_LIST_HEAD (&qh->qtd_list); |
97 | #ifdef CONFIG_CPU_FREQ | ||
98 | INIT_LIST_HEAD (&qh->split_intr_qhs); | ||
99 | #endif | ||
97 | 100 | ||
98 | /* dummy td enables safe urb queuing */ | 101 | /* dummy td enables safe urb queuing */ |
99 | qh->dummy = ehci_qtd_alloc (ehci, flags); | 102 | qh->dummy = ehci_qtd_alloc (ehci, flags); |
@@ -108,13 +111,15 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags) | |||
108 | /* to share a qh (cpu threads, or hc) */ | 111 | /* to share a qh (cpu threads, or hc) */ |
109 | static inline struct ehci_qh *qh_get (struct ehci_qh *qh) | 112 | static inline struct ehci_qh *qh_get (struct ehci_qh *qh) |
110 | { | 113 | { |
111 | kref_get(&qh->kref); | 114 | WARN_ON(!qh->refcount); |
115 | qh->refcount++; | ||
112 | return qh; | 116 | return qh; |
113 | } | 117 | } |
114 | 118 | ||
115 | static inline void qh_put (struct ehci_qh *qh) | 119 | static inline void qh_put (struct ehci_qh *qh) |
116 | { | 120 | { |
117 | kref_put(&qh->kref, qh_destroy); | 121 | if (!--qh->refcount) |
122 | qh_destroy(qh); | ||
118 | } | 123 | } |
119 | 124 | ||
120 | /*-------------------------------------------------------------------------*/ | 125 | /*-------------------------------------------------------------------------*/ |
@@ -217,7 +222,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) | |||
217 | goto fail; | 222 | goto fail; |
218 | } | 223 | } |
219 | for (i = 0; i < ehci->periodic_size; i++) | 224 | for (i = 0; i < ehci->periodic_size; i++) |
220 | ehci->periodic [i] = EHCI_LIST_END; | 225 | ehci->periodic [i] = EHCI_LIST_END(ehci); |
221 | 226 | ||
222 | /* software shadow of hardware table */ | 227 | /* software shadow of hardware table */ |
223 | ehci->pshadow = kcalloc(ehci->periodic_size, sizeof(void *), flags); | 228 | ehci->pshadow = kcalloc(ehci->periodic_size, sizeof(void *), flags); |