Diff markup
1 /* 1 /*
2 * ALSA sequencer Priority Queue 2 * ALSA sequencer Priority Queue
3 * Copyright (c) 1998-1999 by Frank van de P 3 * Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
4 * 4 *
5 * 5 *
6 * This program is free software; you can re 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Pub 7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either vers 8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version. 9 * (at your option) any later version.
10 * 10 *
11 * This program is distributed in the hope t 11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even th 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICUL 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more detai 14 * GNU General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GN 16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to 17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * 19 *
20 */ 20 */
21 21
22 #include <linux/time.h> 22 #include <linux/time.h>
23 #include <linux/slab.h> 23 #include <linux/slab.h>
24 #include <sound/core.h> 24 #include <sound/core.h>
25 #include "seq_timer.h" 25 #include "seq_timer.h"
26 #include "seq_prioq.h" 26 #include "seq_prioq.h"
27 27
28 28
29 /* Implementation is a simple linked list for 29 /* Implementation is a simple linked list for now...
30 30
31 This priority queue orders the events on ti 31 This priority queue orders the events on timestamp. For events with an
32 equeal timestamp the queue behaves as a FIF 32 equeal timestamp the queue behaves as a FIFO.
33 33
34 * 34 *
35 * +-------+ 35 * +-------+
36 * Head --> | first | 36 * Head --> | first |
37 * +-------+ 37 * +-------+
38 * |next 38 * |next
39 * +-----v-+ 39 * +-----v-+
40 * | | 40 * | |
41 * +-------+ 41 * +-------+
42 * | 42 * |
43 * +-----v-+ 43 * +-----v-+
44 * | | 44 * | |
45 * +-------+ 45 * +-------+
46 * | 46 * |
47 * +-----v-+ 47 * +-----v-+
48 * Tail --> | last | 48 * Tail --> | last |
49 * +-------+ 49 * +-------+
50 * 50 *
51 51
52 */ 52 */
53 53
54 54
55 55
56 /* create new prioq (constructor) */ 56 /* create new prioq (constructor) */
57 struct snd_seq_prioq *snd_seq_prioq_new(void) 57 struct snd_seq_prioq *snd_seq_prioq_new(void)
58 { 58 {
59 struct snd_seq_prioq *f; 59 struct snd_seq_prioq *f;
60 60
61 f = kzalloc(sizeof(*f), GFP_KERNEL); 61 f = kzalloc(sizeof(*f), GFP_KERNEL);
62 if (f == NULL) { 62 if (f == NULL) {
63 snd_printd("oops: malloc faile 63 snd_printd("oops: malloc failed for snd_seq_prioq_new()\n");
64 return NULL; 64 return NULL;
65 } 65 }
66 66
67 spin_lock_init(&f->lock); 67 spin_lock_init(&f->lock);
68 f->head = NULL; 68 f->head = NULL;
69 f->tail = NULL; 69 f->tail = NULL;
70 f->cells = 0; 70 f->cells = 0;
71 71
72 return f; 72 return f;
73 } 73 }
74 74
75 /* delete prioq (destructor) */ 75 /* delete prioq (destructor) */
76 void snd_seq_prioq_delete(struct snd_seq_prioq 76 void snd_seq_prioq_delete(struct snd_seq_prioq **fifo)
77 { 77 {
78 struct snd_seq_prioq *f = *fifo; 78 struct snd_seq_prioq *f = *fifo;
79 *fifo = NULL; 79 *fifo = NULL;
80 80
81 if (f == NULL) { 81 if (f == NULL) {
82 snd_printd("oops: snd_seq_prio 82 snd_printd("oops: snd_seq_prioq_delete() called with NULL prioq\n");
83 return; 83 return;
84 } 84 }
85 85
86 /* release resources...*/ 86 /* release resources...*/
87 /*....................*/ 87 /*....................*/
88 88
89 if (f->cells > 0) { 89 if (f->cells > 0) {
90 /* drain prioQ */ 90 /* drain prioQ */
91 while (f->cells > 0) 91 while (f->cells > 0)
92 snd_seq_cell_free(snd_ 92 snd_seq_cell_free(snd_seq_prioq_cell_out(f));
93 } 93 }
94 94
95 kfree(f); 95 kfree(f);
96 } 96 }
97 97
98 98
99 99
100 100
101 /* compare timestamp between events */ 101 /* compare timestamp between events */
102 /* return 1 if a >= b; 0 */ 102 /* return 1 if a >= b; 0 */
103 static inline int compare_timestamp(struct snd 103 static inline int compare_timestamp(struct snd_seq_event *a,
104 struct snd 104 struct snd_seq_event *b)
105 { 105 {
106 if ((a->flags & SNDRV_SEQ_TIME_STAMP_M 106 if ((a->flags & SNDRV_SEQ_TIME_STAMP_MASK) == SNDRV_SEQ_TIME_STAMP_TICK) {
107 /* compare ticks */ 107 /* compare ticks */
108 return (snd_seq_compare_tick_t 108 return (snd_seq_compare_tick_time(&a->time.tick, &b->time.tick));
109 } else { 109 } else {
110 /* compare real time */ 110 /* compare real time */
111 return (snd_seq_compare_real_t 111 return (snd_seq_compare_real_time(&a->time.time, &b->time.time));
112 } 112 }
113 } 113 }
114 114
115 /* compare timestamp between events */ 115 /* compare timestamp between events */
116 /* return negative if a < b; 116 /* return negative if a < b;
117 * zero if a = b; 117 * zero if a = b;
118 * positive if a > b; 118 * positive if a > b;
119 */ 119 */
120 static inline int compare_timestamp_rel(struct 120 static inline int compare_timestamp_rel(struct snd_seq_event *a,
121 struct 121 struct snd_seq_event *b)
122 { 122 {
123 if ((a->flags & SNDRV_SEQ_TIME_STAMP_M 123 if ((a->flags & SNDRV_SEQ_TIME_STAMP_MASK) == SNDRV_SEQ_TIME_STAMP_TICK) {
124 /* compare ticks */ 124 /* compare ticks */
125 if (a->time.tick > b->time.tic 125 if (a->time.tick > b->time.tick)
126 return 1; 126 return 1;
127 else if (a->time.tick == b->ti 127 else if (a->time.tick == b->time.tick)
128 return 0; 128 return 0;
129 else 129 else
130 return -1; 130 return -1;
131 } else { 131 } else {
132 /* compare real time */ 132 /* compare real time */
133 if (a->time.time.tv_sec > b->t 133 if (a->time.time.tv_sec > b->time.time.tv_sec)
134 return 1; 134 return 1;
135 else if (a->time.time.tv_sec = 135 else if (a->time.time.tv_sec == b->time.time.tv_sec) {
136 if (a->time.time.tv_ns 136 if (a->time.time.tv_nsec > b->time.time.tv_nsec)
137 return 1; 137 return 1;
138 else if (a->time.time. 138 else if (a->time.time.tv_nsec == b->time.time.tv_nsec)
139 return 0; 139 return 0;
140 else 140 else
141 return -1; 141 return -1;
142 } else 142 } else
143 return -1; 143 return -1;
144 } 144 }
145 } 145 }
146 146
147 /* enqueue cell to prioq */ 147 /* enqueue cell to prioq */
148 int snd_seq_prioq_cell_in(struct snd_seq_prioq 148 int snd_seq_prioq_cell_in(struct snd_seq_prioq * f,
149 struct snd_seq_event 149 struct snd_seq_event_cell * cell)
150 { 150 {
151 struct snd_seq_event_cell *cur, *prev; 151 struct snd_seq_event_cell *cur, *prev;
152 unsigned long flags; 152 unsigned long flags;
153 int count; 153 int count;
154 int prior; 154 int prior;
155 155
156 snd_assert(f, return -EINVAL); !! 156 if (snd_BUG_ON(!f || !cell))
157 snd_assert(cell, return -EINVAL); !! 157 return -EINVAL;
158 158
159 /* check flags */ 159 /* check flags */
160 prior = (cell->event.flags & SNDRV_SEQ 160 prior = (cell->event.flags & SNDRV_SEQ_PRIORITY_MASK);
161 161
162 spin_lock_irqsave(&f->lock, flags); 162 spin_lock_irqsave(&f->lock, flags);
163 163
164 /* check if this element needs to inse 164 /* check if this element needs to inserted at the end (ie. ordered
165 data is inserted) This will be very 165 data is inserted) This will be very likeley if a sequencer
166 application or midi file player is 166 application or midi file player is feeding us (sequential) data */
167 if (f->tail && !prior) { 167 if (f->tail && !prior) {
168 if (compare_timestamp(&cell->e 168 if (compare_timestamp(&cell->event, &f->tail->event)) {
169 /* add new cell to tai 169 /* add new cell to tail of the fifo */
170 f->tail->next = cell; 170 f->tail->next = cell;
171 f->tail = cell; 171 f->tail = cell;
172 cell->next = NULL; 172 cell->next = NULL;
173 f->cells++; 173 f->cells++;
174 spin_unlock_irqrestore 174 spin_unlock_irqrestore(&f->lock, flags);
175 return 0; 175 return 0;
176 } 176 }
177 } 177 }
178 /* traverse list of elements to find t 178 /* traverse list of elements to find the place where the new cell is
179 to be inserted... Note that this is 179 to be inserted... Note that this is a order n process ! */
180 180
181 prev = NULL; /* previous ce 181 prev = NULL; /* previous cell */
182 cur = f->head; /* cursor */ 182 cur = f->head; /* cursor */
183 183
184 count = 10000; /* FIXME: enough big, i 184 count = 10000; /* FIXME: enough big, isn't it? */
185 while (cur != NULL) { 185 while (cur != NULL) {
186 /* compare timestamps */ 186 /* compare timestamps */
187 int rel = compare_timestamp_re 187 int rel = compare_timestamp_rel(&cell->event, &cur->event);
188 if (rel < 0) 188 if (rel < 0)
189 /* new cell has earlie 189 /* new cell has earlier schedule time, */
190 break; 190 break;
191 else if (rel == 0 && prior) 191 else if (rel == 0 && prior)
192 /* equal schedule time 192 /* equal schedule time and prior to others */
193 break; 193 break;
194 /* new cell has equal or large 194 /* new cell has equal or larger schedule time, */
195 /* move cursor to next cell */ 195 /* move cursor to next cell */
196 prev = cur; 196 prev = cur;
197 cur = cur->next; 197 cur = cur->next;
198 if (! --count) { 198 if (! --count) {
199 spin_unlock_irqrestore 199 spin_unlock_irqrestore(&f->lock, flags);
200 snd_printk(KERN_ERR "c 200 snd_printk(KERN_ERR "cannot find a pointer.. infinite loop?\n");
201 return -EINVAL; 201 return -EINVAL;
202 } 202 }
203 } 203 }
204 204
205 /* insert it before cursor */ 205 /* insert it before cursor */
206 if (prev != NULL) 206 if (prev != NULL)
207 prev->next = cell; 207 prev->next = cell;
208 cell->next = cur; 208 cell->next = cur;
209 209
210 if (f->head == cur) /* this is the fir 210 if (f->head == cur) /* this is the first cell, set head to it */
211 f->head = cell; 211 f->head = cell;
212 if (cur == NULL) /* reached end of the 212 if (cur == NULL) /* reached end of the list */
213 f->tail = cell; 213 f->tail = cell;
214 f->cells++; 214 f->cells++;
215 spin_unlock_irqrestore(&f->lock, flags 215 spin_unlock_irqrestore(&f->lock, flags);
216 return 0; 216 return 0;
217 } 217 }
218 218
219 /* dequeue cell from prioq */ 219 /* dequeue cell from prioq */
220 struct snd_seq_event_cell *snd_seq_prioq_cell_ 220 struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f)
221 { 221 {
222 struct snd_seq_event_cell *cell; 222 struct snd_seq_event_cell *cell;
223 unsigned long flags; 223 unsigned long flags;
224 224
225 if (f == NULL) { 225 if (f == NULL) {
226 snd_printd("oops: snd_seq_prio 226 snd_printd("oops: snd_seq_prioq_cell_in() called with NULL prioq\n");
227 return NULL; 227 return NULL;
228 } 228 }
229 spin_lock_irqsave(&f->lock, flags); 229 spin_lock_irqsave(&f->lock, flags);
230 230
231 cell = f->head; 231 cell = f->head;
232 if (cell) { 232 if (cell) {
233 f->head = cell->next; 233 f->head = cell->next;
234 234
235 /* reset tail if this was the 235 /* reset tail if this was the last element */
236 if (f->tail == cell) 236 if (f->tail == cell)
237 f->tail = NULL; 237 f->tail = NULL;
238 238
239 cell->next = NULL; 239 cell->next = NULL;
240 f->cells--; 240 f->cells--;
241 } 241 }
242 242
243 spin_unlock_irqrestore(&f->lock, flags 243 spin_unlock_irqrestore(&f->lock, flags);
244 return cell; 244 return cell;
245 } 245 }
246 246
247 /* return number of events available in prioq 247 /* return number of events available in prioq */
248 int snd_seq_prioq_avail(struct snd_seq_prioq * 248 int snd_seq_prioq_avail(struct snd_seq_prioq * f)
249 { 249 {
250 if (f == NULL) { 250 if (f == NULL) {
251 snd_printd("oops: snd_seq_prio 251 snd_printd("oops: snd_seq_prioq_cell_in() called with NULL prioq\n");
252 return 0; 252 return 0;
253 } 253 }
254 return f->cells; 254 return f->cells;
255 } 255 }
256 256
257 257
258 /* peek at cell at the head of the prioq */ 258 /* peek at cell at the head of the prioq */
259 struct snd_seq_event_cell *snd_seq_prioq_cell_ 259 struct snd_seq_event_cell *snd_seq_prioq_cell_peek(struct snd_seq_prioq * f)
260 { 260 {
261 if (f == NULL) { 261 if (f == NULL) {
262 snd_printd("oops: snd_seq_prio 262 snd_printd("oops: snd_seq_prioq_cell_in() called with NULL prioq\n");
263 return NULL; 263 return NULL;
264 } 264 }
265 return f->head; 265 return f->head;
266 } 266 }
267 267
268 268
269 static inline int prioq_match(struct snd_seq_e 269 static inline int prioq_match(struct snd_seq_event_cell *cell,
270 int client, int 270 int client, int timestamp)
271 { 271 {
272 if (cell->event.source.client == clien 272 if (cell->event.source.client == client ||
273 cell->event.dest.client == client) 273 cell->event.dest.client == client)
274 return 1; 274 return 1;
275 if (!timestamp) 275 if (!timestamp)
276 return 0; 276 return 0;
277 switch (cell->event.flags & SNDRV_SEQ_ 277 switch (cell->event.flags & SNDRV_SEQ_TIME_STAMP_MASK) {
278 case SNDRV_SEQ_TIME_STAMP_TICK: 278 case SNDRV_SEQ_TIME_STAMP_TICK:
279 if (cell->event.time.tick) 279 if (cell->event.time.tick)
280 return 1; 280 return 1;
281 break; 281 break;
282 case SNDRV_SEQ_TIME_STAMP_REAL: 282 case SNDRV_SEQ_TIME_STAMP_REAL:
283 if (cell->event.time.time.tv_s 283 if (cell->event.time.time.tv_sec ||
284 cell->event.time.time.tv_n 284 cell->event.time.time.tv_nsec)
285 return 1; 285 return 1;
286 break; 286 break;
287 } 287 }
288 return 0; 288 return 0;
289 } 289 }
290 290
291 /* remove cells for left client */ 291 /* remove cells for left client */
292 void snd_seq_prioq_leave(struct snd_seq_prioq 292 void snd_seq_prioq_leave(struct snd_seq_prioq * f, int client, int timestamp)
293 { 293 {
294 register struct snd_seq_event_cell *ce 294 register struct snd_seq_event_cell *cell, *next;
295 unsigned long flags; 295 unsigned long flags;
296 struct snd_seq_event_cell *prev = NULL 296 struct snd_seq_event_cell *prev = NULL;
297 struct snd_seq_event_cell *freefirst = 297 struct snd_seq_event_cell *freefirst = NULL, *freeprev = NULL, *freenext;
298 298
299 /* collect all removed cells */ 299 /* collect all removed cells */
300 spin_lock_irqsave(&f->lock, flags); 300 spin_lock_irqsave(&f->lock, flags);
301 cell = f->head; 301 cell = f->head;
302 while (cell) { 302 while (cell) {
303 next = cell->next; 303 next = cell->next;
304 if (prioq_match(cell, client, 304 if (prioq_match(cell, client, timestamp)) {
305 /* remove cell from pr 305 /* remove cell from prioq */
306 if (cell == f->head) { 306 if (cell == f->head) {
307 f->head = cell 307 f->head = cell->next;
308 } else { 308 } else {
309 prev->next = c 309 prev->next = cell->next;
310 } 310 }
311 if (cell == f->tail) 311 if (cell == f->tail)
312 f->tail = cell 312 f->tail = cell->next;
313 f->cells--; 313 f->cells--;
314 /* add cell to free li 314 /* add cell to free list */
315 cell->next = NULL; 315 cell->next = NULL;
316 if (freefirst == NULL) 316 if (freefirst == NULL) {
317 freefirst = ce 317 freefirst = cell;
318 } else { 318 } else {
319 freeprev->next 319 freeprev->next = cell;
320 } 320 }
321 freeprev = cell; 321 freeprev = cell;
322 } else { 322 } else {
323 #if 0 323 #if 0
324 printk("type = %i, sou !! 324 printk(KERN_DEBUG "type = %i, source = %i, dest = %i, "
>> 325 "client = %i\n",
325 cell->event.ty 326 cell->event.type,
326 cell->event.so 327 cell->event.source.client,
327 cell->event.de 328 cell->event.dest.client,
328 client); 329 client);
329 #endif 330 #endif
330 prev = cell; 331 prev = cell;
331 } 332 }
332 cell = next; 333 cell = next;
333 } 334 }
334 spin_unlock_irqrestore(&f->lock, flags 335 spin_unlock_irqrestore(&f->lock, flags);
335 336
336 /* remove selected cells */ 337 /* remove selected cells */
337 while (freefirst) { 338 while (freefirst) {
338 freenext = freefirst->next; 339 freenext = freefirst->next;
339 snd_seq_cell_free(freefirst); 340 snd_seq_cell_free(freefirst);
340 freefirst = freenext; 341 freefirst = freenext;
341 } 342 }
342 } 343 }
343 344
344 static int prioq_remove_match(struct snd_seq_r 345 static int prioq_remove_match(struct snd_seq_remove_events *info,
345 struct snd_seq_e 346 struct snd_seq_event *ev)
346 { 347 {
347 int res; 348 int res;
348 349
349 if (info->remove_mode & SNDRV_SEQ_REMO 350 if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST) {
350 if (ev->dest.client != info->d 351 if (ev->dest.client != info->dest.client ||
351 ev->dest.port 352 ev->dest.port != info->dest.port)
352 return 0; 353 return 0;
353 } 354 }
354 if (info->remove_mode & SNDRV_SEQ_REMO 355 if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST_CHANNEL) {
355 if (! snd_seq_ev_is_channel_ty 356 if (! snd_seq_ev_is_channel_type(ev))
356 return 0; 357 return 0;
357 /* data.note.channel and data. 358 /* data.note.channel and data.control.channel are identical */
358 if (ev->data.note.channel != i 359 if (ev->data.note.channel != info->channel)
359 return 0; 360 return 0;
360 } 361 }
361 if (info->remove_mode & SNDRV_SEQ_REMO 362 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_AFTER) {
362 if (info->remove_mode & SNDRV_ 363 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK)
363 res = snd_seq_compare_ 364 res = snd_seq_compare_tick_time(&ev->time.tick, &info->time.tick);
364 else 365 else
365 res = snd_seq_compare_ 366 res = snd_seq_compare_real_time(&ev->time.time, &info->time.time);
366 if (!res) 367 if (!res)
367 return 0; 368 return 0;
368 } 369 }
369 if (info->remove_mode & SNDRV_SEQ_REMO 370 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_BEFORE) {
370 if (info->remove_mode & SNDRV_ 371 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK)
371 res = snd_seq_compare_ 372 res = snd_seq_compare_tick_time(&ev->time.tick, &info->time.tick);
372 else 373 else
373 res = snd_seq_compare_ 374 res = snd_seq_compare_real_time(&ev->time.time, &info->time.time);
374 if (res) 375 if (res)
375 return 0; 376 return 0;
376 } 377 }
377 if (info->remove_mode & SNDRV_SEQ_REMO 378 if (info->remove_mode & SNDRV_SEQ_REMOVE_EVENT_TYPE) {
378 if (ev->type != info->type) 379 if (ev->type != info->type)
379 return 0; 380 return 0;
380 } 381 }
381 if (info->remove_mode & SNDRV_SEQ_REMO 382 if (info->remove_mode & SNDRV_SEQ_REMOVE_IGNORE_OFF) {
382 /* Do not remove off events */ 383 /* Do not remove off events */
383 switch (ev->type) { 384 switch (ev->type) {
384 case SNDRV_SEQ_EVENT_NOTEOFF: 385 case SNDRV_SEQ_EVENT_NOTEOFF:
385 /* case SNDRV_SEQ_EVENT_SAMPLE 386 /* case SNDRV_SEQ_EVENT_SAMPLE_STOP: */
386 return 0; 387 return 0;
387 default: 388 default:
388 break; 389 break;
389 } 390 }
390 } 391 }
391 if (info->remove_mode & SNDRV_SEQ_REMO 392 if (info->remove_mode & SNDRV_SEQ_REMOVE_TAG_MATCH) {
392 if (info->tag != ev->tag) 393 if (info->tag != ev->tag)
393 return 0; 394 return 0;
394 } 395 }
395 396
396 return 1; 397 return 1;
397 } 398 }
398 399
399 /* remove cells matching remove criteria */ 400 /* remove cells matching remove criteria */
400 void snd_seq_prioq_remove_events(struct snd_se 401 void snd_seq_prioq_remove_events(struct snd_seq_prioq * f, int client,
401 struct snd_se 402 struct snd_seq_remove_events *info)
402 { 403 {
403 struct snd_seq_event_cell *cell, *next 404 struct snd_seq_event_cell *cell, *next;
404 unsigned long flags; 405 unsigned long flags;
405 struct snd_seq_event_cell *prev = NULL 406 struct snd_seq_event_cell *prev = NULL;
406 struct snd_seq_event_cell *freefirst = 407 struct snd_seq_event_cell *freefirst = NULL, *freeprev = NULL, *freenext;
407 408
408 /* collect all removed cells */ 409 /* collect all removed cells */
409 spin_lock_irqsave(&f->lock, flags); 410 spin_lock_irqsave(&f->lock, flags);
410 cell = f->head; 411 cell = f->head;
411 412
412 while (cell) { 413 while (cell) {
413 next = cell->next; 414 next = cell->next;
414 if (cell->event.source.client 415 if (cell->event.source.client == client &&
415 prioq_remove_match(inf 416 prioq_remove_match(info, &cell->event)) {
416 417
417 /* remove cell from pr 418 /* remove cell from prioq */
418 if (cell == f->head) { 419 if (cell == f->head) {
419 f->head = cell 420 f->head = cell->next;
420 } else { 421 } else {
421 prev->next = c 422 prev->next = cell->next;
422 } 423 }
423 424
424 if (cell == f->tail) 425 if (cell == f->tail)
425 f->tail = cell 426 f->tail = cell->next;
426 f->cells--; 427 f->cells--;
427 428
428 /* add cell to free li 429 /* add cell to free list */
429 cell->next = NULL; 430 cell->next = NULL;
430 if (freefirst == NULL) 431 if (freefirst == NULL) {
431 freefirst = ce 432 freefirst = cell;
432 } else { 433 } else {
433 freeprev->next 434 freeprev->next = cell;
434 } 435 }
435 436
436 freeprev = cell; 437 freeprev = cell;
437 } else { 438 } else {
438 prev = cell; 439 prev = cell;
439 } 440 }
440 cell = next; 441 cell = next;
441 } 442 }
442 spin_unlock_irqrestore(&f->lock, flags 443 spin_unlock_irqrestore(&f->lock, flags);
443 444
444 /* remove selected cells */ 445 /* remove selected cells */
445 while (freefirst) { 446 while (freefirst) {
446 freenext = freefirst->next; 447 freenext = freefirst->next;
447 snd_seq_cell_free(freefirst); 448 snd_seq_cell_free(freefirst);
448 freefirst = freenext; 449 freefirst = freenext;
449 } 450 }
450 } 451 }
451 452
452 453
453 454
|
This page was automatically generated by the
LXR engine.
|