GitLab has been upgraded to 13.3.6. If you encounter any issues mail code@riscosopen.org

Commit c0223aea authored by Jeffrey Lee's avatar Jeffrey Lee

Track latest developments on Raspberry Pi github

Detail:
  Makefile, c/cmodule, h/module, dwc/driver/c/dwc_otg_driver, dwc/driver/c/dwc_otg_hcd, dwc/driver/c/dwc_otg_hcd_ddma, dwc/driver/c/dwc_otg_hcd_intr, dwc/driver/c/dwc_otg_hcd_linex, dwc/driver/h/dwc_otg_hcd, dwc/dwc_common_port/c/dwc_common_linux - Track latest developments on Raspberry Pi github. Includes fixes for buffer overruns when unexpectedly receiving too much data, and changes to allow SOF interrupt spam to be reduced.
  c/dwc_common_riscos - Make sure we always round up delay values when converting from msec to csec. Avoids issues with high frequency timers (e.g. SOF re-enable timer) hogging all the CPU time. May be the cause of some other bad behaviour that I've experienced in the past?
Admin:
  Tested on Raspberry Pi with high processor vectors
  Note - SOF fix is currently disabled, as it was causing too many interrupt packets (e.g. mouse clicks) to be lost. Probable cause is that we're running the SOF re-enable timer at 100Hz instead of 1kHz. May be worth investigating moving all timer/thread scheduling over to a HAL timer which can provide us a 1kHz ticker interrupt.


Version 0.05. Tagged as 'DWCDriver-0_05'
parent eb6b48ef
......@@ -50,6 +50,9 @@ CFLAGS += -DDWC_EN_ISOC -Idwc.dwc_common_port -DDWC_HOST_ONLY -DBCM2835
OBJS += dwc_otg_cil dwc_otg_cil_intr dwc_otg_hcd dwc_otg_hcd_intr dwc_otg_hcd_queue dwc_otg_hcd_ddma
OBJS += dwc_cc dwc_modpow dwc_notifier dwc_mem
# Use this flag to reduce SOF interrupt service overhead
#CFLAGS += -DSOF_FIX
include CModule
${DIRS}::
......
/* (0.04)
/* (0.05)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 0.04
#define Module_MajorVersion_CMHG 0.05
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 24 Jun 2012
#define Module_Date_CMHG 21 Jul 2012
#define Module_MajorVersion "0.04"
#define Module_Version 4
#define Module_MajorVersion "0.05"
#define Module_Version 5
#define Module_MinorVersion ""
#define Module_Date "24 Jun 2012"
#define Module_Date "21 Jul 2012"
#define Module_ApplicationDate "24-Jun-12"
#define Module_ApplicationDate "21-Jul-12"
#define Module_ComponentName "DWCDriver"
#define Module_ComponentPath "mixed/RiscOS/Sources/HWSupport/USB/Controllers/DWCDriver"
#define Module_FullVersion "0.04"
#define Module_HelpVersion "0.04 (24 Jun 2012)"
#define Module_LibraryVersionInfo "0:4"
#define Module_FullVersion "0.05"
#define Module_HelpVersion "0.05 (21 Jul 2012)"
#define Module_LibraryVersionInfo "0:5"
......@@ -460,3 +460,10 @@ int address_valid(void *addr,int align)
return 1;
}
#endif
#ifdef SOF_FIX
int sof_setting(void)
{
return 1;
}
#endif
......@@ -285,9 +285,7 @@ int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t condition,
if(!entry)
return -DWC_E_UNKNOWN;
entry->pollword = 0;
int32_t csecs = msecs/10;
if(csecs*10 != msecs)
csecs++;
int32_t csecs = (msecs+9)/10;
/* Atomic insert and yield */
int irq = ensure_irqs_off();
LIST_INSERT_HEAD(&wq->list,entry,list);
......@@ -583,7 +581,7 @@ void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t work_cb,
workq->idle = 0;
restore_irqs(irq);
/* Register a ticker event that will schedule this task for us */
callx_add_callafter(time/10,delayed_workq_wrapper,e);
callx_add_callafter((time+9)/10,delayed_workq_wrapper,e);
}
int DWC_WORKQ_PENDING(dwc_workq_t *workq)
......@@ -595,7 +593,7 @@ int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq,int timeout)
{
if(workq->idle)
return 0;
timeout = (timeout/10)+1+_swi(OS_ReadMonotonicTime,_RETURN(0));
timeout = ((timeout+9)/10)+1+_swi(OS_ReadMonotonicTime,_RETURN(0));
_swix(RT_TimedYield,_INR(1,2),&workq->idle,timeout);
return (workq->idle?0:-1);
}
......@@ -738,7 +736,7 @@ void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
callx_remove_callafter(timer_wrapper,timer);
}
timer->scheduled = 1;
callx_add_callafter(time/10,timer_wrapper,timer);
callx_add_callafter((time+9)/10,timer_wrapper,timer);
restore_irqs(irqs);
}
......@@ -861,9 +859,7 @@ void DWC_MDELAY(uint32_t msecs)
void DWC_MSLEEP(uint32_t msecs)
{
uint32_t csecs = msecs/10;
if(csecs*10 != msecs)
csecs++;
uint32_t csecs = (msecs+9)/10;
_swix(RT_TimedYield,_INR(1,2),&dummy_pollword_0,csecs+_swi(OS_ReadMonotonicTime,_RETURN(0)));
}
......
......@@ -82,6 +82,11 @@
# include <linux/irq.h>
#ifdef SOF_FIX
#include <asm/uaccess.h>
#include <linux/proc_fs.h>
#endif
#include <asm/io.h>
......@@ -178,6 +183,8 @@ struct dwc_otg_driver_module_params {
int32_t lpm_enable;
int32_t ic_usb_cap;
int32_t ahb_thr_ratio;
int32_t sof_setting; // 0=off, 1=on
int32_t proc_init_done; // 0=not done, 1=done
};
static struct dwc_otg_driver_module_params dwc_otg_module_params = {
......@@ -254,8 +261,138 @@ static struct dwc_otg_driver_module_params dwc_otg_module_params = {
.lpm_enable = -1,
.ic_usb_cap = -1,
.ahb_thr_ratio = -1,
.sof_setting = 0,
.proc_init_done = 0,
};
/**
* PROC_FS SUPPORT
* proc_fs support for setting the Start-of-Frame (SOF) interrupt processing
* fix (reducing SOF interrupts by an order of magnitude). When set
* to "on" the SOF interrupt will only be turned on once per tick, for
* 3 micro-frame times. When set to "off" it will not turn off the
* SOF interrupt, and process all 8000 per second.
*/
#ifdef SOF_FIX
static struct proc_dir_entry *proc_dir, *proc_file;
int sof_setting(void)
{
return dwc_otg_module_params.sof_setting;
}
static int sof_read_data (char *page,
char **start,
off_t off,
int count,
int *eof,
void *data)
{
if (dwc_otg_module_params.sof_setting == 1)
{
sprintf(page, "on\n");
return 4;
}
else
{
sprintf(page, "off\n");
return 5;
}
return 0;
}
#define PROC_FS_MAX_SIZE 1024
#define PROC_FS_NAME "SOF_reduction"
static char proc_fs_buffer[PROC_FS_MAX_SIZE];
static int sof_write_data (struct file *file,
const char __user *buffer,
unsigned long count,
void *data)
{
unsigned long buffer_size = count;
if (buffer_size > PROC_FS_MAX_SIZE)
buffer_size = PROC_FS_MAX_SIZE;
memset(proc_fs_buffer, 0, sizeof(proc_fs_buffer));
if (copy_from_user(proc_fs_buffer, buffer, buffer_size))
{
printk(KERN_ERR "\nSOF_write_data: copy_from_user failure\n");
return -EFAULT;
}
if ((strnlen(proc_fs_buffer, PROC_FS_MAX_SIZE) == 3) &&
(strncmp(proc_fs_buffer, "on", 2) == 0))
{
printk(KERN_ERR "\n%s: Setting SOF (reduction) ON.\n", PROC_FS_NAME);
dwc_otg_module_params.sof_setting = 1;
}
else if ((strnlen(proc_fs_buffer, PROC_FS_MAX_SIZE) == 4) &&
(strncmp(proc_fs_buffer, "off", 3) == 0))
{
printk(KERN_ERR "\n%s: Setting SOF reduction OFF.\n",PROC_FS_NAME);
dwc_otg_module_params.sof_setting = 0;
}
else
printk(KERN_ERR "\n%s: input not \'on\' or \'off\', ignored.\n", PROC_FS_NAME);
#ifdef DEBUG_SOF_FIX
printk(KERN_ERR "\n%s:buffer %s, len = %d.\n",__func__,
proc_fs_buffer, strnlen(proc_fs_buffer, PROC_FS_MAX_SIZE));
#endif
return buffer_size;
}
/**
* Initialize proc_fs entry for SOF setting.
*/
static int init_proc_fs(void)
{
int retval = 0;
if (dwc_otg_module_params.proc_init_done)
return 0;
proc_dir = proc_mkdir_mode("dwc_sof", 0755, NULL);
if(proc_dir == NULL)
{
retval = -ENOMEM;
printk("Error creating dir\n");
return retval;
}
proc_file = create_proc_entry(PROC_FS_NAME, 0666, proc_dir);
if (proc_file != NULL)
{
dwc_otg_module_params.proc_init_done = 1;
proc_file->read_proc = sof_read_data;
proc_file->write_proc = sof_write_data;
proc_file->mode = S_IFREG | S_IRUGO;
proc_file->uid = 0;
proc_file->gid = 0;
proc_file->gid = PROC_FS_MAX_SIZE;
}
else
{
retval = -ENOMEM;
printk("Error creating file\n");
remove_proc_entry(PROC_FS_NAME, NULL);
}
return retval;
}
#endif
/**
* This function shows the Driver Version.
*/
......@@ -845,6 +982,12 @@ struct platform_device *_dev
dev_dbg(&_dev->dev, "Calling attr_create\n");
dwc_otg_attr_create(_dev);
#ifdef SOF_FIX
retval = init_proc_fs();
if (retval)
goto fail;
#endif
/*
* Disable the global interrupt until all the interrupt
* handlers are installed.
......@@ -1015,6 +1158,7 @@ static struct platform_driver dwc_otg_driver = {
*
* @return
*/
static int __init dwc_otg_driver_init(void)
{
int retval = 0;
......@@ -1049,6 +1193,11 @@ static int __init dwc_otg_driver_init(void)
error = driver_create_file(&dwc_otg_driver.driver,
&driver_attr_debuglevel);
#endif
#ifdef SOF_FIX
retval = init_proc_fs();
#endif
return retval;
}
......
......@@ -63,6 +63,37 @@ void dwc_otg_hcd_connect_timeout(void *ptr)
__DWC_ERROR("Device Not Connected/Responding\n");
}
/**
* SOF_FIX: Reduce the SOF overhead by disabling the SOF interrupt except
* when there are USB transfers pending. Re-enable the interrupt
* every tick for periodic transaction handling. MSO 5/31/12
* SOF (Start of Frame) timeout function. Kick the driver by re-enabling
* the SOF interrupt
*/
#ifdef SOF_FIX
void dwc_otg_hcd_sof_timeout(void *ptr)
{
dwc_otg_hcd_t * hcd = (dwc_otg_hcd_t *)ptr;
dwc_otg_core_if_t *core_if = hcd->core_if;
gintmsk_data_t gintmsk = {.d32 = 0};
dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
unsigned int intmsk;
// turn on Start-of-Frame interrupt
gintmsk.d32 = dwc_read_reg32(&global_regs->gintmsk);
intmsk = gintmsk.d32;
gintmsk.b.sofintr |= 1;
dwc_write_reg32(&global_regs->gintmsk, gintmsk.d32);
DWC_TIMER_SCHEDULE(hcd->sof_timer, 1); /* 1ms */
#ifdef DEBUG_SOF_FIX
if ((++sof_timeout_count % 10000) == 0)
printk(KERN_ERR "%s: %d timeouts handled, read 0x%x wrote 0x%x.",
__FUNCTION__, sof_timeout_count, intmsk, gintmsk.d32);
#endif
}
#endif
#ifdef DEBUG
static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
{
......@@ -791,6 +822,13 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer",
dwc_otg_hcd_connect_timeout, 0);
#ifdef SOF_FIX
/* Initialize the Start of Frame interrupt timeout timer. */
hcd->sof_timer = DWC_TIMER_ALLOC("SOF timer",
dwc_otg_hcd_sof_timeout, hcd);
DWC_TIMER_SCHEDULE(hcd->sof_timer, 1); /* 1ms */
#endif
/* Initialize reset tasklet. */
hcd->reset_tasklet = DWC_TASK_ALLOC(reset_tasklet_func, hcd);
......@@ -1306,6 +1344,11 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
dwc_otg_qh_t *qh;
int num_channels;
dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE;
#ifdef SOF_FIX
dwc_otg_core_if_t *core_if = hcd->core_if;
gintmsk_data_t gintmsk = {.d32 = 0};
dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
#endif
#ifdef DEBUG_SOF
DWC_DEBUGPL(DBG_HCD, " Select Transactions\n");
......@@ -1345,6 +1388,19 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
}
#endif
}
#ifdef SOF_FIX
/*
* If there are transactions queued then enable the SOF interrupt to send them to
* the controller.
*/
if (ret_val != DWC_OTG_TRANSACTION_NONE)
{
// turn on Start-of-Frame interrupt
gintmsk.d32 = dwc_read_reg32(&global_regs->gintmsk);
gintmsk.b.sofintr |= 1;
dwc_write_reg32(&global_regs->gintmsk, gintmsk.d32);
}
#endif
/*
* Process entries in the inactive portion of the non-periodic
......
......@@ -886,7 +886,7 @@ uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd,
if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL) {
if (qtd->control_phase == DWC_OTG_CONTROL_DATA) {
urb->actual_length += n_bytes - remain;
if (remain || urb->actual_length == urb->length) {
if (remain || urb->actual_length >= urb->length) {
/*
* For Control Data stage do not set urb->status=0 to prevent
* URB callback. Set it when Status phase done. See below.
......@@ -905,7 +905,7 @@ uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd,
else {
/* BULK and INTR */
urb->actual_length += n_bytes - remain;
if (remain || urb->actual_length == urb->length) {
if (remain || urb->actual_length >= urb->length) {
urb->status = 0;
*xfer_done = 1;
}
......
......@@ -32,6 +32,10 @@
* ========================================================================== */
#ifndef DWC_DEVICE_ONLY
#ifndef __riscos
#include <linux/kernel.h>
#include <linux/module.h>
#endif
#include "dwc_otg_hcd.h"
#include "dwc_otg_regs.h"
......@@ -39,6 +43,19 @@
* This file contains the implementation of the HCD Interrupt handlers.
*/
/**
* SOF_FIX: Reduce SOF interrupt handling by disabling the SOF interrupt except
* when there are actual USB transfers pending. MSO 5/31/12
*/
#ifdef SOF_FIX
extern int sof_setting(void);
unsigned int g_dwc_otg_hcd_handle_intr_count = 0;
#ifdef DEBUG_SOF_FIX
unsigned int g_dwc_otg_interrupt_counts[10] = {0,0,0,0,0,0,0,0,0,0};
extern int g_softintr_ref_cnt;
#endif
#endif
/** This function handles interrupts for the HCD. */
int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
{
......@@ -46,9 +63,12 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
gintsts_data_t gintsts;
#ifdef DEBUG
#ifdef SOF_FIX
dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
gintmsk_data_t gintmsk;
#endif
#ifdef DEBUG
//GRAYG: debugging
if (NULL == global_regs) {
DWC_DEBUGPL(DBG_HCD, "**** NULL regs: dwc_otg_hcd=%p "
......@@ -57,7 +77,9 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
return retval;
}
#endif
#ifdef SOF_FIX
g_dwc_otg_hcd_handle_intr_count++;
#endif
/* Check if HOST Mode */
if (dwc_otg_is_host_mode(core_if)) {
gintsts.d32 = dwc_otg_read_core_intr(core_if);
......@@ -81,29 +103,64 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
gintsts.d32, core_if);
#endif
if (gintsts.b.sofintr) {
/*
* If SOF handle it. If not, it probably means that there is work to do,
* so enable SOF for the next micro-frame.
*/
if (gintsts.b.sofintr)
{
#ifdef DEBUG_SOF_FIX
g_dwc_otg_interrupt_counts[0]++;
#endif
retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
}
#ifdef SOF_FIX
else
{
// turn on Start-of-Frame interrupt
gintmsk.d32 = dwc_read_reg32(&global_regs->gintmsk);
gintmsk.b.sofintr |= 1;
dwc_write_reg32(&global_regs->gintmsk, gintmsk.d32);
}
#endif
if (gintsts.b.rxstsqlvl) {
#ifdef DEBUG_SOF_FIX
g_dwc_otg_interrupt_counts[1]++;
#endif
retval |=
dwc_otg_hcd_handle_rx_status_q_level_intr
(dwc_otg_hcd);
}
if (gintsts.b.nptxfempty) {
#ifdef DEBUG_SOF_FIX
g_dwc_otg_interrupt_counts[2]++;
#endif
retval |=
dwc_otg_hcd_handle_np_tx_fifo_empty_intr
(dwc_otg_hcd);
}
if (gintsts.b.i2cintr) {
#ifdef DEBUG_SOF_FIX
g_dwc_otg_interrupt_counts[3]++;
#endif
/** @todo Implement i2cintr handler. */
}
if (gintsts.b.portintr) {
#ifdef DEBUG_SOF_FIX
g_dwc_otg_interrupt_counts[4]++;
#endif
retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd);
}
if (gintsts.b.hcintr) {
#ifdef DEBUG_SOF_FIX
g_dwc_otg_interrupt_counts[5]++;
#endif
retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd);
}
if (gintsts.b.ptxfempty) {
#ifdef DEBUG_SOF_FIX
g_dwc_otg_interrupt_counts[6]++;
#endif
retval |=
dwc_otg_hcd_handle_perio_tx_fifo_empty_intr
(dwc_otg_hcd);
......@@ -130,7 +187,21 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
#endif
}
#if defined(SOF_FIX) && defined(DEBUG_SOF_FIX)
if ((g_dwc_otg_hcd_handle_intr_count % 80000) == 0)
{
printk(KERN_ERR "dwc_otg_hcd_handle_intr: %u handled, %u, %u, %u, %u, %u, %u, %u, %u.\n",
g_dwc_otg_hcd_handle_intr_count,
g_dwc_otg_interrupt_counts[0],
g_dwc_otg_interrupt_counts[1],
g_dwc_otg_interrupt_counts[2],
g_dwc_otg_interrupt_counts[3],
g_dwc_otg_interrupt_counts[4],
g_dwc_otg_interrupt_counts[5],
g_dwc_otg_interrupt_counts[6],
g_dwc_otg_interrupt_counts[7]);
}
#endif
return retval;
}
......@@ -174,6 +245,10 @@ static inline void track_missed_sofs(uint16_t curr_frame_number)
* (micro)frame. Periodic transactions may be queued to the controller for the
* next (micro)frame.
*/
#ifdef SOF_FIX
#define SOF_INTR_DELAY_COUNT 3
static int g_sof_intr_delay_count = SOF_INTR_DELAY_COUNT;
#endif
int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
{
hfnum_data_t hfnum;
......@@ -181,6 +256,11 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
dwc_otg_qh_t *qh;
dwc_otg_transaction_type_e tr_type;
gintsts_data_t gintsts = {.d32 = 0 };
#ifdef SOF_FIX
dwc_otg_core_if_t *core_if = hcd->core_if;
gintmsk_data_t gintmsk = {.d32 = 0 };
dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
#endif
hfnum.d32 =
dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hfnum);
......@@ -213,9 +293,24 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
}
}
tr_type = dwc_otg_hcd_select_transactions(hcd);
if (tr_type != DWC_OTG_TRANSACTION_NONE) {
if (tr_type != DWC_OTG_TRANSACTION_NONE)
{
dwc_otg_hcd_queue_transactions(hcd, tr_type);
}
#ifdef SOF_FIX
else
{
// turn off Start-of-Frame interrupt
if ((sof_setting()) &&
(g_sof_intr_delay_count-- == 0))
{
gintmsk.d32 = dwc_read_reg32(&global_regs->gintmsk);
gintmsk.b.sofintr &= 0;
dwc_write_reg32(&global_regs->gintmsk, gintmsk.d32);
g_sof_intr_delay_count = SOF_INTR_DELAY_COUNT;
}
}
#endif
/* Clear interrupt */
gintsts.b.sofintr = 1;
......@@ -567,7 +662,7 @@ static int update_urb_state_xfer_comp(dwc_hc_t * hc,
(urb->flags & URB_SEND_ZERO_PACKET) && (urb->actual_length == urb->length) &&
!(urb->length % hc->max_packet)) {
xfer_done = 0;
} else if (short_read || urb->actual_length == urb->length) {
} else if (short_read || urb->actual_length >= urb->length) {
xfer_done = 1;
urb->status = 0;
}
......@@ -1876,10 +1971,10 @@ static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
} else if (hcint.b.xacterr && !hcd->core_if->dma_desc_enable) {
if (out_nak_enh) {
if (hcint.b.nyet || hcint.b.nak || hcint.b.ack) {
DWC_DEBUG("XactErr with NYET/NAK/ACK\n");
DWC_DEBUGPL(DBG_HCD, "XactErr with NYET/NAK/ACK\n");
qtd->error_count = 0;
} else {
DWC_DEBUG("XactErr without NYET/NAK/ACK\n");
DWC_DEBUGPL(DBG_HCD, "XactErr without NYET/NAK/ACK\n");
}
}
......
......@@ -70,6 +70,7 @@
#include "dwc_otg_hcd_if.h"
#include "dwc_otg_dbg.h"
#include "dwc_otg_driver.h"
#include "dwc_otg_hcd.h"
/**
* Gets the endpoint number from a _bEndpointAddress argument. The endpoint is
......@@ -190,6 +191,7 @@ static int _hub_info(dwc_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr,
uint32_t * port_addr)
{
struct urb *urb = (struct urb *)urb_handle;
struct usb_bus *bus;
#if 1 //GRAYG - temporary
if (NULL == urb_handle)
DWC_ERROR("**** %s - NULL URB handle\n", __func__);//GRAYG
......@@ -206,12 +208,18 @@ static int _hub_info(dwc_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr,
*hub_addr = 0; //GRAYG
// we probably shouldn't have a transaction translator if
// there's no associated hub?
} else
*hub_addr = urb->dev->tt->hub->devnum;
} else {
bus = hcd_to_bus(dwc_otg_hcd_to_hcd(hcd));
if (urb->dev->tt->hub == bus->root_hub)
*hub_addr = 0;
else
*hub_addr = urb->dev->tt->hub->devnum;
}
*port_addr = urb->dev->tt->multi ? urb->dev->ttport : 1;
} else {
*hub_addr = 0;
*port_addr = urb->dev->ttport;
}
*port_addr = urb->dev->ttport;
return 0;
}
......@@ -253,10 +261,20 @@ static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
* Sets the final status of an URB and returns it to the device driver. Any
* required cleanup of the URB is performed.
*/
#ifdef DEBUG_SOF_FIX
extern unsigned int g_dwc_otg_interrupt_counts[10];
#endif
static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status)