Blame view

drivers/usb/host/ohci-mem.c 3.32 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
  /*
   * OHCI HCD (Host Controller Driver) for USB.
dd9048af4   David Brownell   USB: ohci whitesp...
3
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
   * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
   * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
dd9048af4   David Brownell   USB: ohci whitesp...
6
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
9
10
11
12
   * This file is licenced under the GPL.
   */
  
  /*-------------------------------------------------------------------------*/
  
  /*
dd9048af4   David Brownell   USB: ohci whitesp...
13
   * OHCI deals with three types of memory:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
16
17
18
19
   *	- data used only by the HCD ... kmalloc is fine
   *	- async and periodic schedules, shared by HC and HCD ... these
   *	  need to use dma_pool or dma_alloc_coherent
   *	- driver buffers, read/written by HC ... the hcd glue or the
   *	  device driver provides us with dma addresses
   *
dd9048af4   David Brownell   USB: ohci whitesp...
20
21
   * There's also "register" data, which is memory mapped.
   * No memory seen by this driver (or any HCD) may be paged out.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
25
26
27
28
29
30
   */
  
  /*-------------------------------------------------------------------------*/
  
  static void ohci_hcd_init (struct ohci_hcd *ohci)
  {
  	ohci->next_statechange = jiffies;
  	spin_lock_init (&ohci->lock);
  	INIT_LIST_HEAD (&ohci->pending);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  }
  
  /*-------------------------------------------------------------------------*/
  
  static int ohci_mem_init (struct ohci_hcd *ohci)
  {
  	ohci->td_cache = dma_pool_create ("ohci_td",
  		ohci_to_hcd(ohci)->self.controller,
  		sizeof (struct td),
  		32 /* byte alignment */,
  		0 /* no page-crossing issues */);
  	if (!ohci->td_cache)
  		return -ENOMEM;
  	ohci->ed_cache = dma_pool_create ("ohci_ed",
  		ohci_to_hcd(ohci)->self.controller,
  		sizeof (struct ed),
  		16 /* byte alignment */,
  		0 /* no page-crossing issues */);
  	if (!ohci->ed_cache) {
  		dma_pool_destroy (ohci->td_cache);
  		return -ENOMEM;
  	}
  	return 0;
  }
  
  static void ohci_mem_cleanup (struct ohci_hcd *ohci)
  {
  	if (ohci->td_cache) {
  		dma_pool_destroy (ohci->td_cache);
  		ohci->td_cache = NULL;
  	}
  	if (ohci->ed_cache) {
  		dma_pool_destroy (ohci->ed_cache);
  		ohci->ed_cache = NULL;
  	}
  }
  
  /*-------------------------------------------------------------------------*/
  
  /* ohci "done list" processing needs this mapping */
  static inline struct td *
  dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
  {
  	struct td *td;
  
  	td_dma &= TD_MASK;
  	td = hc->td_hash [TD_HASH_FUNC(td_dma)];
  	while (td && td->td_dma != td_dma)
  		td = td->td_hash;
  	return td;
  }
  
  /* TDs ... */
  static struct td *
55016f10e   Al Viro   [PATCH] gfp_t: dr...
85
  td_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
  {
  	dma_addr_t	dma;
  	struct td	*td;
  
  	td = dma_pool_alloc (hc->td_cache, mem_flags, &dma);
  	if (td) {
  		/* in case hc fetches it, make it look dead */
  		memset (td, 0, sizeof *td);
  		td->hwNextTD = cpu_to_hc32 (hc, dma);
  		td->td_dma = dma;
  		/* hashed in td_fill */
  	}
  	return td;
  }
  
  static void
  td_free (struct ohci_hcd *hc, struct td *td)
  {
  	struct td	**prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)];
  
  	while (*prev && *prev != td)
  		prev = &(*prev)->td_hash;
  	if (*prev)
  		*prev = td->td_hash;
  	else if ((td->hwINFO & cpu_to_hc32(hc, TD_DONE)) != 0)
  		ohci_dbg (hc, "no hash for td %p
  ", td);
  	dma_pool_free (hc->td_cache, td, td->td_dma);
  }
  
  /*-------------------------------------------------------------------------*/
  
  /* EDs ... */
  static struct ed *
55016f10e   Al Viro   [PATCH] gfp_t: dr...
120
  ed_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
  {
  	dma_addr_t	dma;
  	struct ed	*ed;
  
  	ed = dma_pool_alloc (hc->ed_cache, mem_flags, &dma);
  	if (ed) {
  		memset (ed, 0, sizeof (*ed));
  		INIT_LIST_HEAD (&ed->td_list);
  		ed->dma = dma;
  	}
  	return ed;
  }
  
  static void
  ed_free (struct ohci_hcd *hc, struct ed *ed)
  {
  	dma_pool_free (hc->ed_cache, ed, ed->dma);
  }