Skip to content

Commit 3be22f2

Browse files
P33Mpopcornmix
P33M
authored andcommitted
dwc_otg: make periodic scheduling behave properly for FS buses
If the root port is in full-speed mode, transfer times at 12mbit/s would be calculated but matched against high-speed quotas. Reinitialise hcd->frame_usecs[i] on each port enable event so that full-speed bandwidth can be tracked sensibly. Also, don't bother using the FIQ for transfers when in full-speed mode - at the slower bus speed, interrupt frequency is reduced by an order of magnitude. Related issue: #2020
1 parent d7b6cd3 commit 3be22f2

File tree

4 files changed

+31
-14
lines changed

4 files changed

+31
-14
lines changed

drivers/usb/host/dwc_otg/dwc_otg_hcd.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -926,8 +926,6 @@ static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd)
926926
DWC_FREE(dwc_otg_hcd);
927927
}
928928

929-
int init_hcd_usecs(dwc_otg_hcd_t *_hcd);
930-
931929
int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
932930
{
933931
struct device *dev = dwc_otg_hcd_to_dev(hcd);
@@ -1429,6 +1427,7 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
14291427

14301428
/**
14311429
* fiq_fsm_transaction_suitable() - Test a QH for compatibility with the FIQ
1430+
* @hcd: Pointer to the dwc_otg_hcd struct
14321431
* @qh: pointer to the endpoint's queue head
14331432
*
14341433
* Transaction start/end control flow is grafted onto the existing dwc_otg
@@ -1438,8 +1437,14 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
14381437
* Returns: 0 for unsuitable, 1 implies the FIQ can be enabled for this transaction.
14391438
*/
14401439

1441-
int fiq_fsm_transaction_suitable(dwc_otg_qh_t *qh)
1440+
int fiq_fsm_transaction_suitable(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh)
14421441
{
1442+
/* There is little benefit in using the FIQ to perform transfers if
1443+
* the root port is not in high-speed mode.
1444+
*/
1445+
if (hcd->flags.b.port_speed != DWC_HPRT0_PRTSPD_HIGH_SPEED)
1446+
return 0;
1447+
14431448
if (qh->do_split) {
14441449
switch (qh->ep_type) {
14451450
case UE_CONTROL:
@@ -2218,7 +2223,7 @@ static void process_periodic_channels(dwc_otg_hcd_t * hcd)
22182223
continue;
22192224
}
22202225

2221-
if (fiq_fsm_enable && fiq_fsm_transaction_suitable(qh)) {
2226+
if (fiq_fsm_enable && fiq_fsm_transaction_suitable(hcd, qh)) {
22222227
if (qh->do_split)
22232228
fiq_fsm_queue_split_transaction(hcd, qh);
22242229
else
@@ -2355,7 +2360,7 @@ static void process_non_periodic_channels(dwc_otg_hcd_t * hcd)
23552360
qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
23562361
qh_list_entry);
23572362

2358-
if(fiq_fsm_enable && fiq_fsm_transaction_suitable(qh)) {
2363+
if(fiq_fsm_enable && fiq_fsm_transaction_suitable(hcd, qh)) {
23592364
fiq_fsm_queue_split_transaction(hcd, qh);
23602365
} else {
23612366
status = queue_transaction(hcd, qh->channel,

drivers/usb/host/dwc_otg/dwc_otg_hcd.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,8 @@ struct dwc_otg_hcd {
410410
unsigned port_suspend_change:1;
411411
unsigned port_over_current_change:1;
412412
unsigned port_l1_change:1;
413-
unsigned reserved:26;
413+
unsigned port_speed:2;
414+
unsigned reserved:24;
414415
} b;
415416
} flags;
416417

@@ -629,7 +630,7 @@ int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh);
629630
void dwc_otg_hcd_release_port(dwc_otg_hcd_t * dwc_otg_hcd, dwc_otg_qh_t *qh);
630631

631632
extern int fiq_fsm_queue_transaction(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh);
632-
extern int fiq_fsm_transaction_suitable(dwc_otg_qh_t *qh);
633+
extern int fiq_fsm_transaction_suitable(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh);
633634
extern void dwc_otg_cleanup_fiq_channel(dwc_otg_hcd_t *hcd, uint32_t num);
634635

635636
/** @} */
@@ -823,6 +824,8 @@ static inline uint16_t dwc_micro_frame_num(uint16_t frame)
823824
return frame & 0x7;
824825
}
825826

827+
extern void init_hcd_usecs(dwc_otg_hcd_t *_hcd);
828+
826829
void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
827830
dwc_otg_hc_regs_t * hc_regs,
828831
dwc_otg_qtd_t * qtd);

drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,10 @@ int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd)
515515
dwc_otg_host_if_t *host_if =
516516
dwc_otg_hcd->core_if->host_if;
517517

518+
dwc_otg_hcd->flags.b.port_speed = hprt0.b.prtspd;
519+
if (microframe_schedule)
520+
init_hcd_usecs(dwc_otg_hcd);
521+
518522
/* Every time when port enables calculate
519523
* HFIR.FrInterval
520524
*/

drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -408,13 +408,17 @@ const unsigned short max_uframe_usecs[]={ 100, 100, 100, 100, 100, 100, 30, 0 };
408408
/*
409409
* called from dwc_otg_hcd.c:dwc_otg_hcd_init
410410
*/
411-
int init_hcd_usecs(dwc_otg_hcd_t *_hcd)
411+
void init_hcd_usecs(dwc_otg_hcd_t *_hcd)
412412
{
413413
int i;
414-
for (i=0; i<8; i++) {
415-
_hcd->frame_usecs[i] = max_uframe_usecs[i];
414+
if (_hcd->flags.b.port_speed == DWC_HPRT0_PRTSPD_FULL_SPEED) {
415+
_hcd->frame_usecs[0] = 900;
416+
for (i = 1; i < 8; i++)
417+
_hcd->frame_usecs[i] = 0;
418+
} else {
419+
for (i = 0; i < 8; i++)
420+
_hcd->frame_usecs[i] = max_uframe_usecs[i];
416421
}
417-
return 0;
418422
}
419423

420424
static int find_single_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
@@ -541,8 +545,9 @@ static int find_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
541545
int ret;
542546
ret = -1;
543547

544-
if (_qh->speed == USB_SPEED_HIGH) {
545-
/* if this is a hs transaction we need a full frame */
548+
if (_qh->speed == USB_SPEED_HIGH ||
549+
_hcd->flags.b.port_speed == DWC_HPRT0_PRTSPD_FULL_SPEED) {
550+
/* if this is a hs transaction we need a full frame - or account for FS usecs */
546551
ret = find_single_uframe(_hcd, _qh);
547552
} else {
548553
/* if this is a fs transaction we may need a sequence of frames */
@@ -627,7 +632,7 @@ static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
627632
if (status) {
628633
DWC_INFO("%s: Insufficient periodic bandwidth for "
629634
"periodic transfer.\n", __func__);
630-
return status;
635+
return -DWC_E_NO_SPACE;
631636
}
632637
status = check_max_xfer_size(hcd, qh);
633638
if (status) {

0 commit comments

Comments
 (0)