Skip to content

Commit a0aea52

Browse files
committed
more cache, fix an similar issue with OHCI when removing an queue head
1 parent e4f4ad5 commit a0aea52

File tree

2 files changed

+29
-23
lines changed

2 files changed

+29
-23
lines changed

src/portable/ehci/ehci.c

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ static inline void qtd_remove_1st_from_qhd (ehci_qhd_t *p_qhd);
162162
static void qtd_init (ehci_qtd_t* qtd, void const* buffer, uint16_t total_bytes);
163163

164164
static inline void list_insert (ehci_link_t *current, ehci_link_t *new, uint8_t new_type);
165-
static inline ehci_link_t* list_next (ehci_link_t *p_link_pointer);
165+
static inline ehci_link_t* list_next (ehci_link_t const *p_link);
166166

167167
TU_ATTR_WEAK void hcd_dcache_clean(void* addr, uint32_t data_size) {
168168
(void) addr;
@@ -237,24 +237,22 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport)
237237
return (tusb_speed_t) ehci_data.regs->portsc_bm.nxp_port_speed; // NXP specific port speed
238238
}
239239

240-
static void list_remove_qhd_by_addr(ehci_link_t* list_head, uint8_t dev_addr)
241-
{
242-
for(ehci_link_t* prev = list_head;
243-
!prev->terminate && (tu_align32(prev->address) != (uint32_t) list_head) && prev != NULL;
244-
prev = list_next(prev) )
245-
{
246-
// TODO check type for ISO iTD and siTD
247-
// TODO Suppress cast-align warning
248-
#pragma GCC diagnostic push
249-
#pragma GCC diagnostic ignored "-Wcast-align"
250-
ehci_qhd_t* qhd = (ehci_qhd_t*) list_next(prev);
251-
#pragma GCC diagnostic pop
252-
if ( qhd->dev_addr == dev_addr )
253-
{
240+
static void list_remove_qhd_by_daddr(ehci_link_t* list_head, uint8_t dev_addr) {
241+
ehci_link_t* prev = list_head;
242+
243+
while (prev && !prev->terminate) {
244+
ehci_qhd_t* qhd = (ehci_qhd_t*) (uintptr_t) list_next(prev);
245+
246+
// done if loop back to head
247+
if ( (uintptr_t) qhd == (uintptr_t) list_head) {
248+
break;
249+
}
250+
251+
if ( qhd->dev_addr == dev_addr ) {
254252
// TODO deactivate all TD, wait for QHD to inactive before removal
255253
prev->address = qhd->next.address;
256254

257-
// EHCI 4.8.2 link the removed qhd to async head (which always reachable by Host Controller)
255+
// EHCI 4.8.2 link the removed qhd's next to async head (which always reachable by Host Controller)
258256
qhd->next.address = ((uint32_t) list_head) | (EHCI_QTYPE_QHD << 1);
259257

260258
if ( qhd->int_smask )
@@ -267,6 +265,11 @@ static void list_remove_qhd_by_addr(ehci_link_t* list_head, uint8_t dev_addr)
267265
// mark as removing, will completely re-usable when async advance isr occurs
268266
qhd->removing = 1;
269267
}
268+
269+
hcd_dcache_clean(qhd, sizeof(ehci_qhd_t));
270+
hcd_dcache_clean(prev, sizeof(ehci_qhd_t));
271+
}else {
272+
prev = list_next(prev);
270273
}
271274
}
272275
}
@@ -275,15 +278,16 @@ static void list_remove_qhd_by_addr(ehci_link_t* list_head, uint8_t dev_addr)
275278
void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
276279
{
277280
// skip dev0
278-
if (dev_addr == 0) return;
281+
if (dev_addr == 0) {
282+
return;
283+
}
279284

280285
// Remove from async list
281-
list_remove_qhd_by_addr( (ehci_link_t*) qhd_async_head(rhport), dev_addr );
286+
list_remove_qhd_by_daddr((ehci_link_t *) qhd_async_head(rhport), dev_addr);
282287

283288
// Remove from all interval period list
284-
for(uint8_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++)
285-
{
286-
list_remove_qhd_by_addr( (ehci_link_t*) &ehci_data.period_head_arr[i], dev_addr);
289+
for(uint8_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++) {
290+
list_remove_qhd_by_daddr((ehci_link_t *) &ehci_data.period_head_arr[i], dev_addr);
287291
}
288292

289293
// Async doorbell (EHCI 4.8.2 for operational details)
@@ -990,9 +994,9 @@ static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t n
990994
current->address = ((uint32_t) new) | (new_type << 1);
991995
}
992996

993-
static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer)
997+
static inline ehci_link_t* list_next(ehci_link_t const *p_link)
994998
{
995-
return (ehci_link_t*) tu_align32(p_link_pointer->address);
999+
return (ehci_link_t*) tu_align32(p_link->address);
9961000
}
9971001

9981002
#endif

src/portable/ehci/ehci.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ typedef union {
8181
};
8282
}ehci_link_t;
8383

84+
TU_VERIFY_STATIC( sizeof(ehci_link_t) == 4, "size is not correct" );
85+
8486
/// Queue Element Transfer Descriptor
8587
/// Qtd is used to declare overlay in ehci_qhd_t -> cannot be declared with TU_ATTR_ALIGNED(32)
8688
typedef struct

0 commit comments

Comments
 (0)