linux-old/drivers/usb/auerbuf.c
<<
>>
Prefs
   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
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.