2 * ADM5120 HCD (Host Controller Driver) for USB
4 * Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org>
6 * This file was derived from: drivers/usb/host/ohci-mem.c
7 * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
8 * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
10 * This file is licenced under the GPL.
13 /*-------------------------------------------------------------------------*/
16 * OHCI deals with three types of memory:
17 * - data used only by the HCD ... kmalloc is fine
18 * - async and periodic schedules, shared by HC and HCD ... these
19 * need to use dma_pool or dma_alloc_coherent
20 * - driver buffers, read/written by HC ... the hcd glue or the
21 * device driver provides us with dma addresses
23 * There's also "register" data, which is memory mapped.
24 * No memory seen by this driver (or any HCD) may be paged out.
27 /*-------------------------------------------------------------------------*/
29 static void admhc_hcd_init(struct admhcd
*ahcd
)
31 ahcd
->next_statechange
= jiffies
;
32 spin_lock_init(&ahcd
->lock
);
33 INIT_LIST_HEAD(&ahcd
->pending
);
36 /*-------------------------------------------------------------------------*/
38 static int admhc_mem_init(struct admhcd
*ahcd
)
40 ahcd
->td_cache
= dma_pool_create("admhc_td",
41 admhcd_to_hcd(ahcd
)->self
.controller
,
43 TD_ALIGN
, /* byte alignment */
44 0 /* no page-crossing issues */
49 ahcd
->ed_cache
= dma_pool_create("admhc_ed",
50 admhcd_to_hcd(ahcd
)->self
.controller
,
52 ED_ALIGN
, /* byte alignment */
53 0 /* no page-crossing issues */
61 dma_pool_destroy(ahcd
->td_cache
);
62 ahcd
->td_cache
= NULL
;
67 static void admhc_mem_cleanup(struct admhcd
*ahcd
)
70 dma_pool_destroy(ahcd
->td_cache
);
71 ahcd
->td_cache
= NULL
;
75 dma_pool_destroy(ahcd
->ed_cache
);
76 ahcd
->ed_cache
= NULL
;
80 /*-------------------------------------------------------------------------*/
82 /* ahcd "done list" processing needs this mapping */
83 static inline struct td
*dma_to_td(struct admhcd
*ahcd
, dma_addr_t td_dma
)
88 td
= ahcd
->td_hash
[TD_HASH_FUNC(td_dma
)];
89 while (td
&& td
->td_dma
!= td_dma
)
96 static struct td
*td_alloc(struct admhcd
*ahcd
, gfp_t mem_flags
)
101 td
= dma_pool_alloc(ahcd
->td_cache
, mem_flags
, &dma
);
105 /* in case ahcd fetches it, make it look dead */
106 memset(td
, 0, sizeof *td
);
107 td
->hwNextTD
= cpu_to_hc32(ahcd
, dma
);
109 /* hashed in td_fill */
114 static void td_free(struct admhcd
*ahcd
, struct td
*td
)
116 struct td
**prev
= &ahcd
->td_hash
[TD_HASH_FUNC(td
->td_dma
)];
118 while (*prev
&& *prev
!= td
)
119 prev
= &(*prev
)->td_hash
;
124 else if ((td
->hwINFO
& cpu_to_hc32(ahcd
, TD_DONE
)) != 0)
125 admhc_dbg (ahcd
, "no hash for td %p\n", td
);
127 else if ((td
->flags
& TD_FLAG_DONE
) != 0)
128 admhc_dbg (ahcd
, "no hash for td %p\n", td
);
130 dma_pool_free(ahcd
->td_cache
, td
, td
->td_dma
);
133 /*-------------------------------------------------------------------------*/
136 static struct ed
*ed_alloc(struct admhcd
*ahcd
, gfp_t mem_flags
)
141 ed
= dma_pool_alloc(ahcd
->ed_cache
, mem_flags
, &dma
);
145 memset(ed
, 0, sizeof(*ed
));
148 INIT_LIST_HEAD(&ed
->td_list
);
149 INIT_LIST_HEAD(&ed
->urb_list
);
154 static void ed_free(struct admhcd
*ahcd
, struct ed
*ed
)
156 dma_pool_free(ahcd
->ed_cache
, ed
, ed
->dma
);
159 /*-------------------------------------------------------------------------*/
162 static void urb_priv_free(struct admhcd
*ahcd
, struct urb_priv
*urb_priv
)
166 for (i
= 0; i
< urb_priv
->td_cnt
; i
++)
168 td_free(ahcd
, urb_priv
->td
[i
]);
170 list_del(&urb_priv
->pending
);
174 static struct urb_priv
*urb_priv_alloc(struct admhcd
*ahcd
, int num_tds
,
177 struct urb_priv
*priv
;
179 /* allocate the private part of the URB */
180 priv
= kzalloc(sizeof(*priv
) + sizeof(struct td
) * num_tds
, mem_flags
);
184 /* allocate the TDs (deferring hash chain updates) */
185 for (priv
->td_cnt
= 0; priv
->td_cnt
< num_tds
; priv
->td_cnt
++) {
186 priv
->td
[priv
->td_cnt
] = td_alloc(ahcd
, mem_flags
);
187 if (priv
->td
[priv
->td_cnt
] == NULL
)
191 INIT_LIST_HEAD(&priv
->pending
);
196 urb_priv_free(ahcd
, priv
);
This page took 0.049177 seconds and 5 git commands to generate.