Skip to content

Commit

Permalink
Merge branch 'debug' into rpi-patches
Browse files Browse the repository at this point in the history
Conflicts:
	drivers/usb/host/dwc_otg/dwc_otg_cil.c
	drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
  • Loading branch information
Gordon Hollingworth authored and Gordon Hollingworth committed Sep 3, 2012
2 parents 775d4ce + 18ce78d commit 41e47e6
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 7 deletions.
4 changes: 4 additions & 0 deletions drivers/mmc/host/sdhci.c
Expand Up @@ -967,6 +967,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY)) if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY))
mask |= SDHCI_DATA_INHIBIT; mask |= SDHCI_DATA_INHIBIT;


// This may disable preemption for up to 5s! In real world cases we saw that preemption is stopped for ~150ms which is bad for realtime A/V streaming apps.
if(host->ops->missing_status && (cmd->opcode == MMC_SEND_STATUS)) { if(host->ops->missing_status && (cmd->opcode == MMC_SEND_STATUS)) {
timeout = 5000; // Really obscenely large delay to send the status, due to bug in controller timeout = 5000; // Really obscenely large delay to send the status, due to bug in controller
// which might cause the STATUS command to get stuck when a data operation is in flow // which might cause the STATUS command to get stuck when a data operation is in flow
Expand All @@ -988,7 +989,10 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
return; return;
} }
timeout--; timeout--;
preempt_enable();
schedule();
mdelay(1); mdelay(1);
preempt_disable();
} }
DBG("send cmd %d - wait 0x%X irq 0x%x\n", cmd->opcode, mask, DBG("send cmd %d - wait 0x%X irq 0x%x\n", cmd->opcode, mask,
sdhci_readl(host, SDHCI_INT_STATUS)); sdhci_readl(host, SDHCI_INT_STATUS));
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/host/dwc_otg/dwc_otg_cil.c
Expand Up @@ -2727,6 +2727,7 @@ void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
if (hc->do_split) { if (hc->do_split) {
num_packets = 1; num_packets = 1;


info_data(hc->complete_split ? info_complete_split : info_start_split);
if (hc->complete_split && !hc->ep_is_in) { if (hc->complete_split && !hc->ep_is_in) {
/* For CSPLIT OUT Transfer, set the size to 0 so the /* For CSPLIT OUT Transfer, set the size to 0 so the
* core doesn't expect any data written to the FIFO */ * core doesn't expect any data written to the FIFO */
Expand Down
8 changes: 8 additions & 0 deletions drivers/usb/host/dwc_otg/dwc_otg_dbg.h
Expand Up @@ -30,6 +30,14 @@
#ifndef __DWC_OTG_DBG_H__ #ifndef __DWC_OTG_DBG_H__
#define __DWC_OTG_DBG_H__ #define __DWC_OTG_DBG_H__


#define info_start_split (1 << 0)
#define info_complete_split (1 << 1)
#define info_complete_nyet (1 << 2)
#define info_process_periodic (1 << 3)
#define info_frame (1 << 15)
void info_data(int info);


/** @file /** @file
* This file defines debug levels. * This file defines debug levels.
* Debugging support vanishes in non-debug builds. * Debugging support vanishes in non-debug builds.
Expand Down
4 changes: 4 additions & 0 deletions drivers/usb/host/dwc_otg/dwc_otg_hcd.c
Expand Up @@ -1373,6 +1373,10 @@ static void process_periodic_channels(dwc_otg_hcd_t * hcd)
int no_queue_space = 0; int no_queue_space = 0;
int no_fifo_space = 0; int no_fifo_space = 0;


// OK This is not being called on the right frame, even though we do get every SOF interrupt, need to see if it is
// not actually in the assigned queue at the right time...
info_data(info_process_periodic);

dwc_otg_host_global_regs_t *host_regs; dwc_otg_host_global_regs_t *host_regs;
host_regs = hcd->core_if->host_if->host_global_regs; host_regs = hcd->core_if->host_if->host_global_regs;


Expand Down
66 changes: 60 additions & 6 deletions drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
Expand Up @@ -174,6 +174,19 @@ static inline void track_missed_sofs(uint16_t curr_frame_number)
} }
#endif #endif


struct tracking
{
int frame;
int next_sched;
int info;
} tracking_frames[16];
int tracking_frames_n = 0;

void info_data(int info)
{
tracking_frames[(tracking_frames_n + 15) % 16].info |= info;
}

/** /**
* Handles the start-of-frame interrupt in host mode. Non-periodic * Handles the start-of-frame interrupt in host mode. Non-periodic
* transactions may be queued to the DWC_otg controller for the current * transactions may be queued to the DWC_otg controller for the current
Expand Down Expand Up @@ -204,18 +217,44 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
#ifdef DWC_TRACK_MISSED_SOFS #ifdef DWC_TRACK_MISSED_SOFS
track_missed_sofs(hcd->frame_number); track_missed_sofs(hcd->frame_number);
#endif #endif

qh_entry = DWC_LIST_FIRST(&hcd->periodic_sched_inactive);
next_sched = (DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry))->sched_frame;
while (qh_entry != &hcd->periodic_sched_inactive) {
qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry);
qh_entry = qh_entry->next;
if (dwc_frame_num_le(qh->sched_frame, next_sched)) {
next_sched = qh->sched_frame;
}
}

tracking_frames[tracking_frames_n].frame = hcd->frame_number;
tracking_frames[tracking_frames_n].next_sched = next_sched;
tracking_frames[tracking_frames_n].info = 0;
tracking_frames_n = (tracking_frames_n + 1) % 16;
info_data(info_frame);

/* Determine whether any periodic QHs should be executed. */ /* Determine whether any periodic QHs should be executed. */
qh_entry = DWC_LIST_FIRST(&hcd->periodic_sched_inactive); qh_entry = DWC_LIST_FIRST(&hcd->periodic_sched_inactive);
while (qh_entry != &hcd->periodic_sched_inactive) { while (qh_entry != &hcd->periodic_sched_inactive) {
qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry); qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry);
qh_entry = qh_entry->next; qh_entry = qh_entry->next;
if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) { if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) {
/* dwc_otg_qtd_t * qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
* Move QH to the ready list to be executed next if(qh->do_split && !qtd->complete_split && qh->sched_frame != hcd->frame_number) {
* (micro)frame. if((qh->sched_frame & 7) != 7)
*/ printk("start split not scheduled for frame 7\n");
DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready, qh->sched_frame = hcd->frame_number | 7;
&qh->qh_list_entry); qh->start_split_frame = qh->sched_frame;
}
else {
/*
* Move QH to the ready list to be executed next
* (micro)frame.
*/
DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
&qh->qh_list_entry);
}
} }
} }
tr_type = dwc_otg_hcd_select_transactions(hcd); tr_type = dwc_otg_hcd_select_transactions(hcd);
Expand Down Expand Up @@ -1480,10 +1519,23 @@ static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd,


if (dwc_full_frame_num(frnum) != if (dwc_full_frame_num(frnum) !=
dwc_full_frame_num(hc->qh->sched_frame)) { dwc_full_frame_num(hc->qh->sched_frame)) {
int i;
/* /*
* No longer in the same full speed frame. * No longer in the same full speed frame.
* Treat this as a transaction error. * Treat this as a transaction error.
*/ */
printk(KERN_ERR "Dropping split complete packet, check interrupt latency, scheduled at %d.%d frame number %d.%d start_split_frame = %d.%d\n", hc->qh->sched_frame/8, hc->qh->sched_frame%8, frnum/8, frnum%8, hc->qh->start_split_frame/8, hc->qh->start_split_frame%8);
for(i = 0; i < 16; i++)
{
int info = tracking_frames[(tracking_frames_n + i)%16].info;
int frame = tracking_frames[(tracking_frames_n + i)%16].frame;
int next = tracking_frames[(tracking_frames_n + i)%16].next_sched;
char info_string[32] = "f...........pncs";
int i;
for(i = 0; i < 16; i++)
if(info & (1 << i)) info_string[15-i] = info_string[15-i] + ('A' - 'a');
printk("frame %d.%d - (%d) %s next_sched = %d.%d\n", frame/8, frame%8, info, info_string, next/8, next%8);
}
#if 0 #if 0
/** @todo Fix system performance so this can /** @todo Fix system performance so this can
* be treated as an error. Right now complete * be treated as an error. Right now complete
Expand All @@ -1501,6 +1553,8 @@ static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd,
} }
} }


info_data(info_complete_nyet);

halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET); halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
goto handle_nyet_done; goto handle_nyet_done;
} }
Expand Down
3 changes: 2 additions & 1 deletion drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
Expand Up @@ -598,7 +598,8 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
(qh->sched_frame, frame_number)) { (qh->sched_frame, frame_number)) {
qh->sched_frame = frame_number; qh->sched_frame = frame_number;
} }
qh->sched_frame |= 0x7; // Try to schedule on frame 0...
qh->sched_frame = (qh->sched_frame + 7) & ~7;
qh->start_split_frame = qh->sched_frame; qh->start_split_frame = qh->sched_frame;
} }
} else { } else {
Expand Down

0 comments on commit 41e47e6

Please sign in to comment.