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 26 static 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 33 static 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 40 static 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 58 void 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 64 struct 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 82 void 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 88 struct 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