Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'debug' into rpi-patches

Conflicts:
	drivers/usb/host/dwc_otg/dwc_otg_cil.c
	drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
  • Loading branch information...
commit 41e47e633d343c11b235efecfe8889b31fbe4af8 2 parents 775d4ce + 18ce78d
Gordon Hollingworth authored
View
4 drivers/mmc/host/sdhci.c
@@ -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))
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)) {
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
@@ -988,7 +989,10 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
return;
}
timeout--;
+ preempt_enable();
+ schedule();
mdelay(1);
+ preempt_disable();
}
DBG("send cmd %d - wait 0x%X irq 0x%x\n", cmd->opcode, mask,
sdhci_readl(host, SDHCI_INT_STATUS));
View
1  drivers/usb/host/dwc_otg/dwc_otg_cil.c
@@ -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) {
num_packets = 1;
+ info_data(hc->complete_split ? info_complete_split : info_start_split);
if (hc->complete_split && !hc->ep_is_in) {
/* For CSPLIT OUT Transfer, set the size to 0 so the
* core doesn't expect any data written to the FIFO */
View
8 drivers/usb/host/dwc_otg/dwc_otg_dbg.h
@@ -30,6 +30,14 @@
#ifndef __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
* This file defines debug levels.
* Debugging support vanishes in non-debug builds.
View
4 drivers/usb/host/dwc_otg/dwc_otg_hcd.c
@@ -1373,6 +1373,10 @@ static void process_periodic_channels(dwc_otg_hcd_t * hcd)
int no_queue_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;
host_regs = hcd->core_if->host_if->host_global_regs;
View
66 drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
@@ -174,6 +174,19 @@ static inline void track_missed_sofs(uint16_t curr_frame_number)
}
#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
* transactions may be queued to the DWC_otg controller for the current
@@ -204,18 +217,44 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
#ifdef DWC_TRACK_MISSED_SOFS
track_missed_sofs(hcd->frame_number);
#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. */
qh_entry = DWC_LIST_FIRST(&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_entry = qh_entry->next;
if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) {
- /*
- * Move QH to the ready list to be executed next
- * (micro)frame.
- */
- DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
- &qh->qh_list_entry);
+ dwc_otg_qtd_t * qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
+ if(qh->do_split && !qtd->complete_split && qh->sched_frame != hcd->frame_number) {
+ if((qh->sched_frame & 7) != 7)
+ printk("start split not scheduled for frame 7\n");
+ qh->sched_frame = hcd->frame_number | 7;
+ 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);
@@ -1480,10 +1519,23 @@ static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd,
if (dwc_full_frame_num(frnum) !=
dwc_full_frame_num(hc->qh->sched_frame)) {
+int i;
/*
* No longer in the same full speed frame.
* 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
/** @todo Fix system performance so this can
* be treated as an error. Right now complete
@@ -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);
goto handle_nyet_done;
}
View
3  drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
@@ -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 |= 0x7;
+ // Try to schedule on frame 0...
+ qh->sched_frame = (qh->sched_frame + 7) & ~7;
qh->start_split_frame = qh->sched_frame;
}
} else {
Please sign in to comment.
Something went wrong with that request. Please try again.