• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
init_td(struct td * td)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 
init_ed(struct ed * ed)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 
get_empty_td(struct fhci_hcd * fhci)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 
fhci_recycle_empty_td(struct fhci_hcd * fhci,struct td * td)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 
fhci_get_empty_ed(struct fhci_hcd * fhci)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 
fhci_recycle_empty_ed(struct fhci_hcd * fhci,struct ed * ed)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 
fhci_td_fill(struct fhci_hcd * fhci,struct urb * urb,struct urb_priv * urb_priv,struct ed * ed,u16 index,enum fhci_ta_type type,int toggle,u8 * data,u32 len,u16 interval,u16 start_frame,bool ioc)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