fhci-mem.c revision 236dd4d18f293e3c9798f35c08272196826a980d
1/* 2 * Freescale QUICC Engine USB Host Controller Driver 3 * 4 * Copyright (c) Freescale Semicondutor, Inc. 2006. 5 * Shlomi Gridish <gridish@freescale.com> 6 * Jerry Huang <Chang-Ming.Huang@freescale.com> 7 * Copyright (c) Logic Product Development, Inc. 2007 8 * Peter Barada <peterb@logicpd.com> 9 * Copyright (c) MontaVista Software, Inc. 2008. 10 * Anton Vorontsov <avorontsov@ru.mvista.com> 11 * 12 * This program is free software; you can redistribute it and/or modify it 13 * under the terms of the GNU General Public License as published by the 14 * Free Software Foundation; either version 2 of the License, or (at your 15 * option) any later version. 16 */ 17 18#include <linux/kernel.h> 19#include <linux/types.h> 20#include <linux/delay.h> 21#include <linux/list.h> 22#include <linux/usb.h> 23#include "../core/hcd.h" 24#include "fhci.h" 25 26static void init_td(struct td *td) 27{ 28 memset(td, 0, sizeof(*td)); 29 INIT_LIST_HEAD(&td->node); 30 INIT_LIST_HEAD(&td->frame_lh); 31} 32 33static void init_ed(struct ed *ed) 34{ 35 memset(ed, 0, sizeof(*ed)); 36 INIT_LIST_HEAD(&ed->td_list); 37 INIT_LIST_HEAD(&ed->node); 38} 39 40static struct td *get_empty_td(struct fhci_hcd *fhci) 41{ 42 struct td *td; 43 44 if (!list_empty(&fhci->empty_tds)) { 45 td = list_entry(fhci->empty_tds.next, struct td, node); 46 list_del(fhci->empty_tds.next); 47 } else { 48 td = kmalloc(sizeof(*td), GFP_ATOMIC); 49 if (!td) 50 fhci_err(fhci, "No memory to allocate to TD\n"); 51 else 52 init_td(td); 53 } 54 55 return td; 56} 57 58void fhci_recycle_empty_td(struct fhci_hcd *fhci, struct td *td) 59{ 60 init_td(td); 61 list_add(&td->node, &fhci->empty_tds); 62} 63 64struct ed *fhci_get_empty_ed(struct fhci_hcd *fhci) 65{ 66 struct ed *ed; 67 68 if (!list_empty(&fhci->empty_eds)) { 69 ed = list_entry(fhci->empty_eds.next, struct ed, node); 70 list_del(fhci->empty_eds.next); 71 } else { 72 ed = kmalloc(sizeof(*ed), GFP_ATOMIC); 73 if (!ed) 74 fhci_err(fhci, "No memory to allocate to ED\n"); 75 else 76 init_ed(ed); 77 } 78 79 return ed; 80} 81 82void fhci_recycle_empty_ed(struct fhci_hcd *fhci, struct ed *ed) 83{ 84 init_ed(ed); 85 list_add(&ed->node, &fhci->empty_eds); 86} 87 88struct td *fhci_td_fill(struct fhci_hcd *fhci, struct urb *urb, 89 struct urb_priv *urb_priv, struct ed *ed, u16 index, 90 enum fhci_ta_type type, int toggle, u8 *data, u32 len, 91 u16 interval, u16 start_frame, bool ioc) 92{ 93 struct td *td = get_empty_td(fhci); 94 95 if (!td) 96 return NULL; 97 98 td->urb = urb; 99 td->ed = ed; 100 td->type = type; 101 td->toggle = toggle; 102 td->data = data; 103 td->len = len; 104 td->iso_index = index; 105 td->interval = interval; 106 td->start_frame = start_frame; 107 td->ioc = ioc; 108 td->status = USB_TD_OK; 109 110 urb_priv->tds[index] = td; 111 112 return td; 113} 114