diff options
Diffstat (limited to 'target/linux/cns3xxx/files/drivers/usb/dwc/otg_hcd.h')
-rw-r--r-- | target/linux/cns3xxx/files/drivers/usb/dwc/otg_hcd.h | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/target/linux/cns3xxx/files/drivers/usb/dwc/otg_hcd.h b/target/linux/cns3xxx/files/drivers/usb/dwc/otg_hcd.h index 935f353..cef2879 100644 --- a/target/linux/cns3xxx/files/drivers/usb/dwc/otg_hcd.h +++ b/target/linux/cns3xxx/files/drivers/usb/dwc/otg_hcd.h @@ -194,6 +194,11 @@ typedef struct dwc_otg_qh { */ uint16_t sched_frame; + /* + * Frame a NAK was received on this queue head, used to minimise NAK retransmission + */ + uint16_t nak_frame; + /** (micro)frame at which last start split was initialized. */ uint16_t start_split_frame; @@ -328,6 +333,21 @@ typedef struct dwc_otg_hcd { struct list_head free_hc_list; /** + * The number of bulk channels in the active schedule that do + * not have a halt pending or queued but received at least one + * nak and thus are probably blocking a host channel. + * + * This number is included in non_perodic_channels as well. + */ + int nakking_channels; + + /** + * The number of the last host channel that was halted to free + * up a host channel. + */ + int last_channel_halted; + + /** * Number of host channels assigned to periodic transfers. Currently * assuming that there is a dedicated host channel for each periodic * transaction and at least one host channel available for @@ -452,6 +472,8 @@ extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t *hcd, dwc_otg_transaction_type_e tr_type); extern void dwc_otg_hcd_complete_urb(dwc_otg_hcd_t *_hcd, struct urb *urb, int status); +extern dwc_hc_t *dwc_otg_halt_nakking_channel(dwc_otg_hcd_t *hcd); + /** @} */ /** @name Interrupt Handler Functions */ @@ -612,6 +634,40 @@ static inline uint16_t dwc_micro_frame_num(uint16_t frame) return frame & 0x7; } +/* Perform some sanity checks on nakking / non_perodic channel states. */ +static inline int check_nakking(struct dwc_otg_hcd *hcd, const char *func, const char* context) { +#ifdef DEBUG + int nakking = 0, non_periodic = 0, i; + int num_channels = hcd->core_if->core_params->host_channels; + for (i = 0; i < num_channels; i++) { + dwc_hc_t *hc = hcd->hc_ptr_array[i]; + if (hc->xfer_started + && (hc->ep_type == DWC_OTG_EP_TYPE_BULK + || hc->ep_type == DWC_OTG_EP_TYPE_CONTROL)) { + non_periodic++; + } + if (hc->xfer_started + && !hc->halt_on_queue + && !hc->halt_pending + && hc->qh->nak_frame != 0xffff) { + nakking++; + } + } + + if (nakking != hcd->nakking_channels + || nakking > hcd->non_periodic_channels + || non_periodic != hcd->non_periodic_channels) { + printk("%s/%s: Inconsistent nakking state\n", func, context); + printk("non_periodic: %d, real %d, nakking: %d, real %d\n", hcd->non_periodic_channels, non_periodic, hcd->nakking_channels, nakking); + dwc_otg_hcd_dump_state(hcd); + WARN_ON(1); + return 1; + } +#endif + return 0; +} + + #ifdef DEBUG /** * Macro to sample the remaining PHY clocks left in the current frame. This |