1 // SPDX-License-Identifier: GPL-2.0+
3 * Freescale QUICC Engine USB Host Controller Driver
5 * Copyright (c) Freescale Semicondutor, Inc. 2006.
6 * Shlomi Gridish <gridish@freescale.com>
7 * Jerry Huang <Chang-Ming.Huang@freescale.com>
8 * Copyright (c) Logic Product Development, Inc. 2007
9 * Peter Barada <peterb@logicpd.com>
10 * Copyright (c) MontaVista Software, Inc. 2008.
11 * Anton Vorontsov <avorontsov@ru.mvista.com>
14 #include <linux/kernel.h>
15 #include <linux/types.h>
16 #include <linux/delay.h>
17 #include <linux/slab.h>
18 #include <linux/list.h>
19 #include <linux/usb.h>
20 #include <linux/usb/hcd.h>
23 static void init_td(struct td
*td
)
25 memset(td
, 0, sizeof(*td
));
26 INIT_LIST_HEAD(&td
->node
);
27 INIT_LIST_HEAD(&td
->frame_lh
);
30 static void init_ed(struct ed
*ed
)
32 memset(ed
, 0, sizeof(*ed
));
33 INIT_LIST_HEAD(&ed
->td_list
);
34 INIT_LIST_HEAD(&ed
->node
);
37 static struct td
*get_empty_td(struct fhci_hcd
*fhci
)
41 if (!list_empty(&fhci
->empty_tds
)) {
42 td
= list_entry(fhci
->empty_tds
.next
, struct td
, node
);
43 list_del(fhci
->empty_tds
.next
);
45 td
= kmalloc(sizeof(*td
), GFP_ATOMIC
);
47 fhci_err(fhci
, "No memory to allocate to TD\n");
55 void fhci_recycle_empty_td(struct fhci_hcd
*fhci
, struct td
*td
)
58 list_add(&td
->node
, &fhci
->empty_tds
);
61 struct ed
*fhci_get_empty_ed(struct fhci_hcd
*fhci
)
65 if (!list_empty(&fhci
->empty_eds
)) {
66 ed
= list_entry(fhci
->empty_eds
.next
, struct ed
, node
);
67 list_del(fhci
->empty_eds
.next
);
69 ed
= kmalloc(sizeof(*ed
), GFP_ATOMIC
);
71 fhci_err(fhci
, "No memory to allocate to ED\n");
79 void fhci_recycle_empty_ed(struct fhci_hcd
*fhci
, struct ed
*ed
)
82 list_add(&ed
->node
, &fhci
->empty_eds
);
85 struct td
*fhci_td_fill(struct fhci_hcd
*fhci
, struct urb
*urb
,
86 struct urb_priv
*urb_priv
, struct ed
*ed
, u16 index
,
87 enum fhci_ta_type type
, int toggle
, u8
*data
, u32 len
,
88 u16 interval
, u16 start_frame
, bool ioc
)
90 struct td
*td
= get_empty_td(fhci
);
101 td
->iso_index
= index
;
102 td
->interval
= interval
;
103 td
->start_frame
= start_frame
;
105 td
->status
= USB_TD_OK
;
107 urb_priv
->tds
[index
] = td
;