1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#undef DEBUG
24#include <linux/usb.h>
25#include "auerbuf.h"
26#include <linux/slab.h>
27
28
29void auerbuf_free(struct auerbuf *bp)
30{
31 if (!bp) return;
32 kfree(bp->bufp);
33 kfree(bp->dr);
34 if (bp->urbp) {
35 usb_free_urb(bp->urbp);
36 }
37 kfree(bp);
38}
39
40
41void auerbuf_free_list(struct list_head *q)
42{
43 struct list_head *tmp;
44 struct list_head *p;
45 struct auerbuf *bp;
46
47 dbg("auerbuf_free_list");
48 for (p = q->next; p != q;) {
49 bp = list_entry(p, struct auerbuf, buff_list);
50 tmp = p->next;
51 list_del(p);
52 p = tmp;
53 auerbuf_free(bp);
54 }
55}
56
57
58void auerbuf_free_buffers(struct auerbufctl *bcp)
59{
60 unsigned long flags;
61 dbg("auerbuf_free_buffers");
62
63 spin_lock_irqsave(&bcp->lock, flags);
64
65 auerbuf_free_list(&bcp->free_buff_list);
66 auerbuf_free_list(&bcp->rec_buff_list);
67
68 spin_unlock_irqrestore(&bcp->lock, flags);
69}
70
71
72void auerbuf_init(struct auerbufctl *bcp)
73{
74 dbg("auerbuf_init");
75 spin_lock_init(&bcp->lock);
76 INIT_LIST_HEAD(&bcp->free_buff_list);
77 INIT_LIST_HEAD(&bcp->rec_buff_list);
78}
79
80
81
82int auerbuf_setup(struct auerbufctl *bcp, unsigned int numElements,
83 unsigned int bufsize)
84{
85 struct auerbuf *bep = NULL;
86
87 dbg("auerbuf_setup called with %d elements of %d bytes",
88 numElements, bufsize);
89
90
91 for (; numElements; numElements--) {
92 bep =
93 (struct auerbuf *) kmalloc(sizeof(struct auerbuf),
94 GFP_KERNEL);
95 if (!bep)
96 goto bl_fail;
97 memset(bep, 0, sizeof(struct auerbuf));
98 bep->list = bcp;
99 INIT_LIST_HEAD(&bep->buff_list);
100 bep->bufp = (char *) kmalloc(bufsize, GFP_KERNEL);
101 if (!bep->bufp)
102 goto bl_fail;
103 bep->dr =
104 (struct usb_ctrlrequest *)
105 kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
106 if (!bep->dr)
107 goto bl_fail;
108 bep->urbp = usb_alloc_urb(0);
109 if (!bep->urbp)
110 goto bl_fail;
111 list_add_tail(&bep->buff_list, &bcp->free_buff_list);
112 }
113 return 0;
114
115 bl_fail:
116 dbg("auerbuf_setup: no more memory");
117 auerbuf_free (bep);
118 auerbuf_free_buffers(bcp);
119 return -ENOMEM;
120}
121
122
123struct auerbuf *auerbuf_getbuf(struct auerbufctl *bcp)
124{
125 unsigned long flags;
126 struct auerbuf *bp = NULL;
127
128 spin_lock_irqsave(&bcp->lock, flags);
129 if (!list_empty(&bcp->free_buff_list)) {
130
131 struct list_head *tmp = bcp->free_buff_list.next;
132 list_del(tmp);
133 bp = list_entry(tmp, struct auerbuf, buff_list);
134 }
135 spin_unlock_irqrestore(&bcp->lock, flags);
136 return bp;
137}
138
139
140void auerbuf_releasebuf(struct auerbuf *bp)
141{
142 unsigned long flags;
143 struct auerbufctl *bcp = bp->list;
144 bp->retries = 0;
145
146 dbg("auerbuf_releasebuf called");
147 spin_lock_irqsave(&bcp->lock, flags);
148 list_add_tail(&bp->buff_list, &bcp->free_buff_list);
149 spin_unlock_irqrestore(&bcp->lock, flags);
150}
151