1/*****************************************************************************/ 2/* 3 * auerbuf.c -- Auerswald PBX/System Telephone urb list storage. 4 * 5 * Copyright (C) 2002 Wolfgang M�es (wolfgang@iksw-muees.de) 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 /*****************************************************************************/ 22 23#undef DEBUG /* include debug macros until it's done */ 24#include <linux/usb.h> 25#include "auerbuf.h" 26#include <linux/slab.h> 27 28/* free a single auerbuf */ 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/* free the buffers from an auerbuf list */ 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/* free all buffers from an auerbuf chain */ 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/* init the members of a list control block */ 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/* setup a list of buffers */ 81/* requirement: auerbuf_init() */ 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 /* fill the list of free elements */ 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: /* not enought memory. Free allocated elements */ 116 dbg("auerbuf_setup: no more memory"); 117 auerbuf_free (bep); 118 auerbuf_free_buffers(bcp); 119 return -ENOMEM; 120} 121 122/* alloc a free buffer from the list. Returns NULL if no buffer available */ 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 /* yes: get the entry */ 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/* insert a used buffer into the free list */ 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