File: | ozeltbuf.c |
Location: | line 166, column 6 |
Description: | Branch condition evaluates to a garbage value |
1 | /* ----------------------------------------------------------------------------- | |||
2 | * Copyright (c) 2011 Ozmo Inc | |||
3 | * Released under the GNU General Public License Version 2 (GPLv2). | |||
4 | * ----------------------------------------------------------------------------- | |||
5 | */ | |||
6 | #include <linux1/init.h> | |||
7 | #include <linux1/module.h> | |||
8 | #include <linux1/netdevice.h> | |||
9 | #include "ozconfig.h" | |||
10 | #include "ozprotocol.h" | |||
11 | #include "ozeltbuf.h" | |||
12 | #include "ozpd.h" | |||
13 | #include "oztrace.h" | |||
14 | /*------------------------------------------------------------------------------ | |||
15 | */ | |||
16 | #define OZ_ELT_INFO_MAGIC_USED0x35791057 0x35791057 | |||
17 | #define OZ_ELT_INFO_MAGIC_FREE0x78940102 0x78940102 | |||
18 | /*------------------------------------------------------------------------------ | |||
19 | * Context: softirq-serialized | |||
20 | */ | |||
21 | int oz_elt_buf_init(struct oz_elt_buf *buf) | |||
22 | { | |||
23 | memset(buf, 0, sizeof(struct oz_elt_buf)); | |||
24 | INIT_LIST_HEAD(&buf->stream_list); | |||
25 | INIT_LIST_HEAD(&buf->order_list); | |||
26 | INIT_LIST_HEAD(&buf->isoc_list); | |||
27 | buf->max_free_elts = 32; | |||
28 | spin_lock_init(&buf->lock)do { spinlock_check(&buf->lock); do { *(&(&buf ->lock)->rlock) = (raw_spinlock_t) { .raw_lock = { { 0 } }, }; } while (0); } while (0); | |||
29 | return 0; | |||
30 | } | |||
31 | /*------------------------------------------------------------------------------ | |||
32 | * Context: softirq or process | |||
33 | */ | |||
34 | void oz_elt_buf_term(struct oz_elt_buf *buf) | |||
35 | { | |||
36 | struct list_head *e; | |||
37 | int i; | |||
38 | /* Free any elements in the order or isoc lists. */ | |||
39 | for (i = 0; i < 2; i++) { | |||
40 | struct list_head *list; | |||
41 | if (i) | |||
42 | list = &buf->order_list; | |||
43 | else | |||
44 | list = &buf->isoc_list; | |||
45 | e = list->next; | |||
46 | while (e != list) { | |||
47 | struct oz_elt_info *ei = | |||
48 | container_of(e, struct oz_elt_info, link_order)({ const typeof( ((struct oz_elt_info *)0)->link_order ) * __mptr = (e); (struct oz_elt_info *)( (char *)__mptr - __builtin_offsetof (struct oz_elt_info,link_order) );}); | |||
49 | e = e->next; | |||
50 | kfree(ei); | |||
51 | } | |||
52 | } | |||
53 | /* Free any elelment in the pool. */ | |||
54 | while (buf->elt_pool) { | |||
55 | struct oz_elt_info *ei = | |||
56 | container_of(buf->elt_pool, struct oz_elt_info, link)({ const typeof( ((struct oz_elt_info *)0)->link ) *__mptr = (buf->elt_pool); (struct oz_elt_info *)( (char *)__mptr - __builtin_offsetof(struct oz_elt_info,link) );}); | |||
57 | buf->elt_pool = buf->elt_pool->next; | |||
58 | kfree(ei); | |||
59 | } | |||
60 | buf->free_elts = 0; | |||
61 | } | |||
62 | /*------------------------------------------------------------------------------ | |||
63 | * Context: softirq or process | |||
64 | */ | |||
65 | struct oz_elt_info *oz_elt_info_alloc(struct oz_elt_buf *buf) | |||
66 | { | |||
67 | struct oz_elt_info *ei = NULL((void *)0); | |||
68 | spin_lock_bh(&buf->lock); | |||
69 | if (buf->free_elts && buf->elt_pool) { | |||
70 | ei = container_of(buf->elt_pool, struct oz_elt_info, link)({ const typeof( ((struct oz_elt_info *)0)->link ) *__mptr = (buf->elt_pool); (struct oz_elt_info *)( (char *)__mptr - __builtin_offsetof(struct oz_elt_info,link) );}); | |||
71 | buf->elt_pool = ei->link.next; | |||
72 | buf->free_elts--; | |||
73 | spin_unlock_bh(&buf->lock); | |||
74 | if (ei->magic != OZ_ELT_INFO_MAGIC_FREE0x78940102) { | |||
75 | oz_trace("oz_elt_info_alloc: ei with bad magic: 0x%x\n", | |||
76 | ei->magic); | |||
77 | } | |||
78 | } else { | |||
79 | spin_unlock_bh(&buf->lock); | |||
80 | ei = kmalloc(sizeof(struct oz_elt_info), GFP_ATOMIC((( gfp_t)0x20u))); | |||
81 | } | |||
82 | if (ei) { | |||
83 | ei->flags = 0; | |||
84 | ei->app_id = 0; | |||
85 | ei->callback = NULL((void *)0); | |||
86 | ei->context = 0; | |||
87 | ei->stream = NULL((void *)0); | |||
88 | ei->magic = OZ_ELT_INFO_MAGIC_USED0x35791057; | |||
89 | INIT_LIST_HEAD(&ei->link); | |||
90 | INIT_LIST_HEAD(&ei->link_order); | |||
91 | } | |||
92 | return ei; | |||
93 | } | |||
94 | /*------------------------------------------------------------------------------ | |||
95 | * Precondition: oz_elt_buf.lock must be held. | |||
96 | * Context: softirq or process | |||
97 | */ | |||
98 | void oz_elt_info_free(struct oz_elt_buf *buf, struct oz_elt_info *ei) | |||
99 | { | |||
100 | if (ei) { | |||
101 | if (ei->magic == OZ_ELT_INFO_MAGIC_USED0x35791057) { | |||
102 | buf->free_elts++; | |||
103 | ei->link.next = buf->elt_pool; | |||
104 | buf->elt_pool = &ei->link; | |||
105 | ei->magic = OZ_ELT_INFO_MAGIC_FREE0x78940102; | |||
106 | } else { | |||
107 | oz_trace("oz_elt_info_free: bad magic ei: %p" | |||
108 | " magic: 0x%x\n", | |||
109 | ei, ei->magic); | |||
110 | } | |||
111 | } | |||
112 | } | |||
113 | /*------------------------------------------------------------------------------ | |||
114 | * Context: softirq | |||
115 | */ | |||
116 | void oz_elt_info_free_chain(struct oz_elt_buf *buf, struct list_head *list) | |||
117 | { | |||
118 | struct list_head *e; | |||
119 | e = list->next; | |||
120 | spin_lock_bh(&buf->lock); | |||
121 | while (e != list) { | |||
122 | struct oz_elt_info *ei; | |||
123 | ei = container_of(e, struct oz_elt_info, link)({ const typeof( ((struct oz_elt_info *)0)->link ) *__mptr = (e); (struct oz_elt_info *)( (char *)__mptr - __builtin_offsetof (struct oz_elt_info,link) );}); | |||
124 | e = e->next; | |||
125 | oz_elt_info_free(buf, ei); | |||
126 | } | |||
127 | spin_unlock_bh(&buf->lock); | |||
128 | } | |||
129 | /*------------------------------------------------------------------------------ | |||
130 | */ | |||
131 | int oz_elt_stream_create(struct oz_elt_buf *buf, u8 id, int max_buf_count) | |||
132 | { | |||
133 | struct oz_elt_stream *st; | |||
134 | ||||
135 | oz_trace("oz_elt_stream_create(0x%x)\n", id); | |||
136 | ||||
137 | st = kzalloc(sizeof(struct oz_elt_stream), GFP_ATOMIC((( gfp_t)0x20u)) | __GFP_ZERO(( gfp_t)0x8000u)); | |||
138 | if (st == NULL((void *)0)) | |||
139 | return -ENOMEM12; | |||
140 | atomic_set(&st->ref_count, 1); | |||
141 | st->id = id; | |||
142 | st->max_buf_count = max_buf_count; | |||
143 | INIT_LIST_HEAD(&st->elt_list); | |||
144 | spin_lock_bh(&buf->lock); | |||
145 | list_add_tail(&st->link, &buf->stream_list); | |||
146 | spin_unlock_bh(&buf->lock); | |||
147 | return 0; | |||
148 | } | |||
149 | /*------------------------------------------------------------------------------ | |||
150 | */ | |||
151 | int oz_elt_stream_delete(struct oz_elt_buf *buf, u8 id) | |||
152 | { | |||
153 | struct list_head *e; | |||
154 | struct oz_elt_stream *st; | |||
155 | oz_trace("oz_elt_stream_delete(0x%x)\n", id); | |||
156 | spin_lock_bh(&buf->lock); | |||
| ||||
157 | e = buf->stream_list.next; | |||
158 | while (e != &buf->stream_list) { | |||
159 | st = container_of(e, struct oz_elt_stream, link)({ const typeof( ((struct oz_elt_stream *)0)->link ) *__mptr = (e); (struct oz_elt_stream *)( (char *)__mptr - __builtin_offsetof (struct oz_elt_stream,link) );}); | |||
160 | if (st->id == id) { | |||
161 | list_del(e); | |||
162 | break; | |||
163 | } | |||
164 | st = NULL((void *)0); | |||
165 | } | |||
166 | if (!st) { | |||
| ||||
167 | spin_unlock_bh(&buf->lock); | |||
168 | return -1; | |||
169 | } | |||
170 | e = st->elt_list.next; | |||
171 | while (e != &st->elt_list) { | |||
172 | struct oz_elt_info *ei = | |||
173 | container_of(e, struct oz_elt_info, link)({ const typeof( ((struct oz_elt_info *)0)->link ) *__mptr = (e); (struct oz_elt_info *)( (char *)__mptr - __builtin_offsetof (struct oz_elt_info,link) );}); | |||
174 | e = e->next; | |||
175 | list_del_init(&ei->link); | |||
176 | list_del_init(&ei->link_order); | |||
177 | st->buf_count -= ei->length; | |||
178 | oz_trace2(OZ_TRACE_STREAM, "Stream down: %d %d %d\n", | |||
179 | st->buf_count, | |||
180 | ei->length, atomic_read(&st->ref_count)); | |||
181 | oz_elt_stream_put(st); | |||
182 | oz_elt_info_free(buf, ei); | |||
183 | } | |||
184 | spin_unlock_bh(&buf->lock); | |||
185 | oz_elt_stream_put(st); | |||
186 | return 0; | |||
187 | } | |||
188 | /*------------------------------------------------------------------------------ | |||
189 | */ | |||
190 | void oz_elt_stream_get(struct oz_elt_stream *st) | |||
191 | { | |||
192 | atomic_inc(&st->ref_count); | |||
193 | } | |||
194 | /*------------------------------------------------------------------------------ | |||
195 | */ | |||
196 | void oz_elt_stream_put(struct oz_elt_stream *st) | |||
197 | { | |||
198 | if (atomic_dec_and_test(&st->ref_count)) { | |||
199 | oz_trace("Stream destroyed\n"); | |||
200 | kfree(st); | |||
201 | } | |||
202 | } | |||
203 | /*------------------------------------------------------------------------------ | |||
204 | * Precondition: Element buffer lock must be held. | |||
205 | * If this function fails the caller is responsible for deallocating the elt | |||
206 | * info structure. | |||
207 | */ | |||
208 | int oz_queue_elt_info(struct oz_elt_buf *buf, u8 isoc, u8 id, | |||
209 | struct oz_elt_info *ei) | |||
210 | { | |||
211 | struct oz_elt_stream *st = NULL((void *)0); | |||
212 | struct list_head *e; | |||
213 | if (id) { | |||
214 | list_for_each(e, &buf->stream_list)for (e = (&buf->stream_list)->next; e != (&buf-> stream_list); e = e->next) { | |||
215 | st = container_of(e, struct oz_elt_stream, link)({ const typeof( ((struct oz_elt_stream *)0)->link ) *__mptr = (e); (struct oz_elt_stream *)( (char *)__mptr - __builtin_offsetof (struct oz_elt_stream,link) );}); | |||
216 | if (st->id == id) | |||
217 | break; | |||
218 | } | |||
219 | if (e == &buf->stream_list) { | |||
220 | /* Stream specified but stream not known so fail. | |||
221 | * Caller deallocates element info. */ | |||
222 | return -1; | |||
223 | } | |||
224 | } | |||
225 | if (st) { | |||
226 | /* If this is an ISOC fixed element that needs a frame number | |||
227 | * then insert that now. Earlier we stored the unit count in | |||
228 | * this field. | |||
229 | */ | |||
230 | struct oz_isoc_fixed *body = (struct oz_isoc_fixed *) | |||
231 | &ei->data[sizeof(struct oz_elt)]; | |||
232 | if ((body->app_id == OZ_APPID_USB0x1) && (body->type | |||
233 | == OZ_USB_ENDPOINT_DATA23) && | |||
234 | (body->format == OZ_DATA_F_ISOC_FIXED0x3)) { | |||
235 | u8 unit_count = body->frame_number; | |||
236 | body->frame_number = st->frame_number; | |||
237 | st->frame_number += unit_count; | |||
238 | } | |||
239 | /* Claim stream and update accounts */ | |||
240 | oz_elt_stream_get(st); | |||
241 | ei->stream = st; | |||
242 | st->buf_count += ei->length; | |||
243 | /* Add to list in stream. */ | |||
244 | list_add_tail(&ei->link, &st->elt_list); | |||
245 | oz_trace2(OZ_TRACE_STREAM, "Stream up: %d %d\n", | |||
246 | st->buf_count, ei->length); | |||
247 | /* Check if we have too much buffered for this stream. If so | |||
248 | * start dropping elements until we are back in bounds. | |||
249 | */ | |||
250 | while ((st->buf_count > st->max_buf_count) && | |||
251 | !list_empty(&st->elt_list)) { | |||
252 | struct oz_elt_info *ei2 = | |||
253 | list_first_entry(&st->elt_list,({ const typeof( ((struct oz_elt_info *)0)->link ) *__mptr = ((&st->elt_list)->next); (struct oz_elt_info *)( (char *)__mptr - __builtin_offsetof(struct oz_elt_info,link) );}) | |||
254 | struct oz_elt_info, link)({ const typeof( ((struct oz_elt_info *)0)->link ) *__mptr = ((&st->elt_list)->next); (struct oz_elt_info *)( (char *)__mptr - __builtin_offsetof(struct oz_elt_info,link) );}); | |||
255 | list_del_init(&ei2->link); | |||
256 | list_del_init(&ei2->link_order); | |||
257 | st->buf_count -= ei2->length; | |||
258 | oz_elt_info_free(buf, ei2); | |||
259 | oz_elt_stream_put(st); | |||
260 | } | |||
261 | } | |||
262 | list_add_tail(&ei->link_order, isoc ? | |||
263 | &buf->isoc_list : &buf->order_list); | |||
264 | return 0; | |||
265 | } | |||
266 | /*------------------------------------------------------------------------------ | |||
267 | */ | |||
268 | int oz_select_elts_for_tx(struct oz_elt_buf *buf, u8 isoc, unsigned *len, | |||
269 | unsigned max_len, struct list_head *list) | |||
270 | { | |||
271 | int count = 0; | |||
272 | struct list_head *e; | |||
273 | struct list_head *el; | |||
274 | struct oz_elt_info *ei; | |||
275 | spin_lock_bh(&buf->lock); | |||
276 | if (isoc) | |||
277 | el = &buf->isoc_list; | |||
278 | else | |||
279 | el = &buf->order_list; | |||
280 | e = el->next; | |||
281 | while (e != el) { | |||
282 | struct oz_app_hdr *app_hdr; | |||
283 | ei = container_of(e, struct oz_elt_info, link_order)({ const typeof( ((struct oz_elt_info *)0)->link_order ) * __mptr = (e); (struct oz_elt_info *)( (char *)__mptr - __builtin_offsetof (struct oz_elt_info,link_order) );}); | |||
284 | e = e->next; | |||
285 | if ((*len + ei->length) <= max_len) { | |||
286 | app_hdr = (struct oz_app_hdr *) | |||
287 | &ei->data[sizeof(struct oz_elt)]; | |||
288 | app_hdr->elt_seq_num = buf->tx_seq_num[ei->app_id]++; | |||
289 | if (buf->tx_seq_num[ei->app_id] == 0) | |||
290 | buf->tx_seq_num[ei->app_id] = 1; | |||
291 | *len += ei->length; | |||
292 | list_del(&ei->link); | |||
293 | list_del(&ei->link_order); | |||
294 | if (ei->stream) { | |||
295 | ei->stream->buf_count -= ei->length; | |||
296 | oz_trace2(OZ_TRACE_STREAM, | |||
297 | "Stream down: %d %d\n", | |||
298 | ei->stream->buf_count, ei->length); | |||
299 | oz_elt_stream_put(ei->stream); | |||
300 | ei->stream = NULL((void *)0); | |||
301 | } | |||
302 | INIT_LIST_HEAD(&ei->link_order); | |||
303 | list_add_tail(&ei->link, list); | |||
304 | count++; | |||
305 | } else { | |||
306 | break; | |||
307 | } | |||
308 | } | |||
309 | spin_unlock_bh(&buf->lock); | |||
310 | return count; | |||
311 | } | |||
312 | /*------------------------------------------------------------------------------ | |||
313 | */ | |||
314 | int oz_are_elts_available(struct oz_elt_buf *buf) | |||
315 | { | |||
316 | return buf->order_list.next != &buf->order_list; | |||
317 | } | |||
318 | /*------------------------------------------------------------------------------ | |||
319 | */ | |||
320 | void oz_trim_elt_pool(struct oz_elt_buf *buf) | |||
321 | { | |||
322 | struct list_head *free = NULL((void *)0); | |||
323 | struct list_head *e; | |||
324 | spin_lock_bh(&buf->lock); | |||
325 | while (buf->free_elts > buf->max_free_elts) { | |||
326 | e = buf->elt_pool; | |||
327 | buf->elt_pool = e->next; | |||
328 | e->next = free; | |||
329 | free = e; | |||
330 | buf->free_elts--; | |||
331 | } | |||
332 | spin_unlock_bh(&buf->lock); | |||
333 | while (free) { | |||
334 | struct oz_elt_info *ei = | |||
335 | container_of(free, struct oz_elt_info, link)({ const typeof( ((struct oz_elt_info *)0)->link ) *__mptr = (free); (struct oz_elt_info *)( (char *)__mptr - __builtin_offsetof (struct oz_elt_info,link) );}); | |||
336 | free = free->next; | |||
337 | kfree(ei); | |||
338 | } | |||
339 | } |