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