Skip to content

Commit ec4bd39

Browse files
committed
refactor ehci: add attached_buffer for dcache invalidate for IN transfer
1 parent 27acaa0 commit ec4bd39

File tree

2 files changed

+72
-52
lines changed

2 files changed

+72
-52
lines changed

src/portable/ehci/ehci.c

Lines changed: 67 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ static inline ehci_qhd_t* qhd_next (ehci_qhd_t const * p_qhd);
154154
static inline ehci_qhd_t* qhd_find_free (void);
155155
static inline ehci_qhd_t* qhd_get_from_addr (uint8_t dev_addr, uint8_t ep_addr);
156156
static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc);
157+
static void qhd_attach_qtd(ehci_qhd_t *qhd, ehci_qtd_t *qtd);
157158

158159
static inline ehci_qtd_t* qtd_find_free (void);
159160
static void qtd_init (ehci_qtd_t* qtd, void const* buffer, uint16_t total_bytes);
@@ -468,13 +469,9 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet
468469
td->pid = EHCI_PID_SETUP;
469470

470471
hcd_dcache_clean((void *) setup_packet, 8);
471-
hcd_dcache_clean_invalidate(td, sizeof(ehci_qtd_t));
472472

473-
// attach TD
474-
qhd->p_attached_qtd = td; // software management
475-
qhd->qtd_overlay.next.address = (uint32_t) td;
476-
477-
hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t));
473+
// attach TD to QHD -> start transferring
474+
qhd_attach_qtd(qhd, td);
478475

479476
return true;
480477
}
@@ -513,13 +510,9 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
513510
}else {
514511
hcd_dcache_clean(buffer, buflen);
515512
}
516-
hcd_dcache_clean_invalidate(qtd, sizeof(ehci_qtd_t));
517513

518-
// attach TD to QHD start transferring
519-
qhd->p_attached_qtd = qtd; // software management
520-
qhd->qtd_overlay.next.address = (uint32_t) qtd;
521-
522-
hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t));
514+
// attach TD to QHD -> start transferring
515+
qhd_attach_qtd(qhd, qtd);
523516

524517
return true;
525518
}
@@ -569,10 +562,9 @@ void port_connect_status_change_isr(uint8_t rhport)
569562
}
570563

571564
TU_ATTR_ALWAYS_INLINE static inline
572-
void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd)
573-
{
565+
void qhd_xfer_complete_isr(ehci_qhd_t * qhd) {
574566
// examine TD attached to queue head
575-
ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_attached_qtd;
567+
ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) qhd->attached_qtd;
576568
if (qtd == NULL) return; // no TD attached
577569
hcd_dcache_invalidate(qtd, sizeof(ehci_qtd_t));
578570

@@ -581,15 +573,22 @@ void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd)
581573
return;
582574
}
583575

576+
uint8_t dir = (qtd->pid == EHCI_PID_IN) ? 1 : 0;
584577
uint32_t const xferred_bytes = qtd->expected_bytes - qtd->total_bytes;
585-
uint8_t const ep_addr = tu_edpt_addr(p_qhd->ep_number, qtd->pid == EHCI_PID_IN ? 1 : 0);
578+
579+
// invalidate dcache if IN transfer
580+
if (dir == 1 && qhd->attached_buffer != 0) {
581+
hcd_dcache_invalidate((void*) qhd->attached_buffer, xferred_bytes);
582+
}
586583

587584
// remove and free TD before invoking callback
588-
p_qhd->p_attached_qtd = NULL;
585+
qhd->attached_qtd = NULL;
586+
qhd->attached_buffer = 0;
589587
qtd->used = 0; // free QTD
590588

591-
// IOC is always set
592-
hcd_event_xfer_complete(p_qhd->dev_addr, ep_addr, xferred_bytes, XFER_RESULT_SUCCESS, true);
589+
// notify usbh
590+
uint8_t const ep_addr = tu_edpt_addr(qhd->ep_number, dir);
591+
hcd_event_xfer_complete(qhd->dev_addr, ep_addr, xferred_bytes, XFER_RESULT_SUCCESS, true);
593592
}
594593

595594
TU_ATTR_ALWAYS_INLINE static inline
@@ -651,10 +650,11 @@ void period_list_xfer_complete_isr(uint8_t rhport, uint32_t interval_ms)
651650
}
652651
}
653652

653+
// TODO merge with qhd_xfer_complete_isr()
654654
TU_ATTR_ALWAYS_INLINE static inline
655-
void qhd_xfer_error_isr(ehci_qhd_t * p_qhd)
655+
void qhd_xfer_error_isr(ehci_qhd_t * qhd)
656656
{
657-
volatile ehci_qtd_t *qtd_overlay = &p_qhd->qtd_overlay;
657+
volatile ehci_qtd_t *qtd_overlay = &qhd->qtd_overlay;
658658

659659
// TD has error
660660
if (qtd_overlay->halted) {
@@ -674,28 +674,37 @@ void qhd_xfer_error_isr(ehci_qhd_t * p_qhd)
674674
// while(1){}
675675
// }
676676

677-
ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_attached_qtd;
677+
ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) qhd->attached_qtd;
678678
TU_ASSERT(qtd, ); // No TD yet, probably a race condition or cache issue !?
679679

680680
hcd_dcache_invalidate(qtd, sizeof(ehci_qtd_t));
681+
682+
uint8_t dir = (qtd->pid == EHCI_PID_IN) ? 1 : 0;
681683
uint32_t const xferred_bytes = qtd->expected_bytes - qtd->total_bytes;
682684

683-
p_qhd->p_attached_qtd = NULL;
685+
// invalidate dcache if IN transfer
686+
if (dir == 1 && qhd->attached_buffer != 0) {
687+
hcd_dcache_invalidate((void*) qhd->attached_buffer, xferred_bytes);
688+
}
689+
690+
// remove and free TD before invoking callback
691+
qhd->attached_qtd = NULL;
692+
qhd->attached_buffer = 0;
684693
qtd->used = 0; // free QTD
685694

686-
if ( 0 == p_qhd->ep_number ) {
695+
if (0 == qhd->ep_number ) {
687696
// control cannot be halted
688-
p_qhd->qtd_overlay.next.terminate = 1;
689-
p_qhd->qtd_overlay.alternate.terminate = 1;
690-
p_qhd->qtd_overlay.halted = 0;
697+
qhd->qtd_overlay.next.terminate = 1;
698+
qhd->qtd_overlay.alternate.terminate = 1;
699+
qhd->qtd_overlay.halted = 0;
691700

692-
ehci_qtd_t *p_setup = qtd_control(p_qhd->dev_addr);
701+
ehci_qtd_t *p_setup = qtd_control(qhd->dev_addr);
693702
p_setup->used = 0;
694703
}
695704

696705
// notify usbh
697-
uint8_t const ep_addr = tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0);
698-
hcd_event_xfer_complete(p_qhd->dev_addr, ep_addr, xferred_bytes, xfer_result, true);
706+
uint8_t const ep_addr = tu_edpt_addr(qhd->ep_number, dir);
707+
hcd_event_xfer_complete(qhd->dev_addr, ep_addr, xferred_bytes, xfer_result, true);
699708
}
700709
}
701710

@@ -846,22 +855,10 @@ static inline ehci_qhd_t* qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr)
846855
return NULL;
847856
}
848857

849-
//------------- TD helper -------------//
850-
static inline ehci_qtd_t* qtd_find_free(void)
851-
{
852-
for (uint32_t i=0; i<QTD_MAX; i++)
853-
{
854-
if ( !ehci_data.qtd_pool[i].used ) return &ehci_data.qtd_pool[i];
855-
}
856-
857-
return NULL;
858-
}
859-
860858
static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc)
861859
{
862860
// address 0 is used as async head, which always on the list --> cannot be cleared (ehci halted otherwise)
863-
if (dev_addr != 0)
864-
{
861+
if (dev_addr != 0) {
865862
tu_memclr(p_qhd, sizeof(ehci_qhd_t));
866863
}
867864

@@ -911,26 +908,47 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c
911908
p_qhd->int_smask = p_qhd->fl_int_cmask = 0;
912909
}
913910

914-
p_qhd->fl_hub_addr = devtree_info.hub_addr;
915-
p_qhd->fl_hub_port = devtree_info.hub_port;
916-
p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet
911+
p_qhd->fl_hub_addr = devtree_info.hub_addr;
912+
p_qhd->fl_hub_port = devtree_info.hub_port;
913+
p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet
917914

918915
//------------- HCD Management Data -------------//
919-
p_qhd->used = 1;
920-
p_qhd->removing = 0;
921-
p_qhd->p_attached_qtd = NULL;
916+
p_qhd->used = 1;
917+
p_qhd->removing = 0;
918+
p_qhd->attached_qtd = NULL;
922919
p_qhd->pid = tu_edpt_dir(ep_desc->bEndpointAddress) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint
923920

924921
//------------- active, but no TD list -------------//
925922
p_qhd->qtd_overlay.halted = 0;
926923
p_qhd->qtd_overlay.next.terminate = 1;
927924
p_qhd->qtd_overlay.alternate.terminate = 1;
925+
928926
if (TUSB_XFER_BULK == xfer_type && p_qhd->ep_speed == TUSB_SPEED_HIGH && p_qhd->pid == EHCI_PID_OUT)
929927
{
930928
p_qhd->qtd_overlay.ping_err = 1; // do PING for Highspeed Bulk OUT, EHCI section 4.11
931929
}
932930
}
933931

932+
static void qhd_attach_qtd(ehci_qhd_t *qhd, ehci_qtd_t *qtd) {
933+
qhd->attached_qtd = qtd;
934+
qhd->attached_buffer = qtd->buffer[0];
935+
936+
// clean and invalidate cache before physically write
937+
hcd_dcache_clean_invalidate(qtd, sizeof(ehci_qtd_t));
938+
939+
qhd->qtd_overlay.next.address = (uint32_t) qtd;
940+
hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t));
941+
}
942+
943+
944+
//------------- TD helper -------------//
945+
static inline ehci_qtd_t *qtd_find_free(void) {
946+
for (uint32_t i = 0; i < QTD_MAX; i++) {
947+
if (!ehci_data.qtd_pool[i].used) return &ehci_data.qtd_pool[i];
948+
}
949+
return NULL;
950+
}
951+
934952
static void qtd_init(ehci_qtd_t* qtd, void const* buffer, uint16_t total_bytes)
935953
{
936954
tu_memclr(qtd, sizeof(ehci_qtd_t));

src/portable/ehci/ehci.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,12 @@ typedef struct TU_ATTR_ALIGNED(32)
164164
uint8_t pid;
165165
uint8_t interval_ms; // polling interval in frames (or millisecond)
166166

167-
uint8_t TU_RESERVED[8];
167+
uint8_t TU_RESERVED[4];
168168

169-
// usbh will only queue 1 TD per QHD
170-
ehci_qtd_t * volatile p_attached_qtd;
169+
// Attached TD management, note usbh will only queue 1 TD per QHD.
170+
// buffer for dcache invalidate since td's buffer is modified by HC and finding initial buffer address is not trivial
171+
uint32_t attached_buffer;
172+
ehci_qtd_t * volatile attached_qtd;
171173
} ehci_qhd_t;
172174

173175
TU_VERIFY_STATIC( sizeof(ehci_qhd_t) == 64, "size is not correct" );

0 commit comments

Comments
 (0)