diff options
author | Nikunj A Dadhania <nikunj@linux.vnet.ibm.com> | 2013-09-24 15:09:29 +0530 |
---|---|---|
committer | Nikunj A Dadhania <nikunj@linux.vnet.ibm.com> | 2013-10-04 12:01:21 +0530 |
commit | 80ba6519d89df92174d02c21f2f19d1f11282637 (patch) | |
tree | 074dd6cb212f8daa0ce2b6e257ab8a3852ddc28a | |
parent | a351fc0cbc823aff137f55aea33c9923475482e3 (diff) | |
download | SLOF-80ba6519d89df92174d02c21f2f19d1f11282637.zip SLOF-80ba6519d89df92174d02c21f2f19d1f11282637.tar.gz SLOF-80ba6519d89df92174d02c21f2f19d1f11282637.tar.bz2 |
usb-ohci: done_head processing fixes
Return error code like STALL back, so it can be handled effectively.
Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
-rw-r--r-- | lib/libusb/usb-ohci.c | 72 | ||||
-rw-r--r-- | lib/libusb/usb-ohci.h | 6 |
2 files changed, 42 insertions, 36 deletions
diff --git a/lib/libusb/usb-ohci.c b/lib/libusb/usb-ohci.c index 3cd91e1..b959cd3 100644 --- a/lib/libusb/usb-ohci.c +++ b/lib/libusb/usb-ohci.c @@ -414,7 +414,8 @@ static int ohci_process_done_head(struct ohci_hcd *ohcd, struct ohci_hcca *hcca; struct ohci_td *td_phys = NULL, *td_start_phys; struct ohci_td *td, *prev_td = NULL; - uint32_t reg = 0, start_frame = 0, time = 0, ret = true; + uint32_t reg = 0, start_frame = 0, time = 0; + int ret = true; long count; count = total_count; @@ -442,8 +443,12 @@ static int ohci_process_done_head(struct ohci_hcd *ohcd, cpu_relax(); } mb(); - hcca->done_head = 0; - mb(); + + if (time < SLOF_GetTimer()) { + ret = false; + break; + } + td = (struct ohci_td *)(uint64_t) ohci_get_td_virt(td_phys, td_start_phys, PTR_U32(td_start), total_count); @@ -459,8 +464,13 @@ static int ohci_process_done_head(struct ohci_hcd *ohcd, mb(); reg = (le32_to_cpu(td->attr) & TDA_CC) >> 28; if (reg) { + dprintf("%s: cbp %08X attr %08X next_td %08X be %08X\n", + __func__, + le32_to_cpu(td->cbp), le32_to_cpu(td->attr), + le32_to_cpu(td->next_td), le32_to_cpu(td->be)); printf("USB: Error %s %p\n", tda_cc_error[reg], td); - ret = false; + if (reg > 3) /* Return negative error code */ + ret = reg * -1; } prev_td = td; td_phys = (struct ohci_td *)(uint64_t) le32_to_cpu(td->next_td); @@ -554,16 +564,16 @@ static int ohci_send_ctrl(struct usb_pipe *pipe, struct usb_dev_req *req, void * if ((ed->headp & EDA_HEADP_MASK_LE) == ed->tailp) { dprintf("%s: packet sent\n", __func__); #ifdef OHCI_DEBUG_PACKET + dpprintf("Request: "); + dbuf = (unsigned char *)req; + for(i = 0; i < 8; i++) + printf("%02X ", dbuf[i]); + dpprintf("\n"); if (datalen) { - dpprintf("Request: "); - dbuf = (unsigned char *)req; - for(i = 0; i < 8; i++) - dpprintf("%02X ", dbuf[i]); - dpprintf("\n"); dbuf = (unsigned char *)data; dpprintf("Reply: "); for(i = 0; i < datalen; i++) - dpprintf("%02X ", dbuf[i]); + printf("%02X ", dbuf[i]); dpprintf("\n"); } #endif @@ -574,6 +584,11 @@ static int ohci_send_ctrl(struct usb_pipe *pipe, struct usb_dev_req *req, void * __func__, le32_to_cpu(ed->headp), le32_to_cpu(ed->tailp), le32_to_cpu(ed->next_ed), le32_to_cpu(ed->attr)); + printf("Request: "); + dbuf = (unsigned char *)req; + for(i = 0; i < 8; i++) + printf("%02X ", dbuf[i]); + printf("\n"); } ret = ohci_process_done_head(ohcd, tds, (long)td_phys, td_count); mb(); @@ -582,20 +597,12 @@ static int ohci_send_ctrl(struct usb_pipe *pipe, struct usb_dev_req *req, void * write_reg32(®s->cntl_head_ed, 0); write_reg32(®s->cntl_curr_ed, 0); - if (!ret) { - printf("Request: "); - dbuf = (unsigned char *)req; - for(i = 0; i < 8; i++) - printf("%02X ", dbuf[i]); - printf("\n"); - } - SLOF_dma_map_out(req_phys, req, sizeof(struct usb_dev_req)); if (datalen) SLOF_dma_map_out(data_phys, data, datalen); SLOF_dma_map_out(PTR_U32(td_phys), tds, sizeof(*td) * OHCI_CTRL_TDS); SLOF_dma_free(tds, sizeof(*td) * OHCI_CTRL_TDS); - return ret; + return (ret > 0) ? true : false; } static int ohci_transfer_bulk(struct usb_pipe *pipe, void *td_ptr, @@ -610,10 +617,6 @@ static int ohci_transfer_bulk(struct usb_pipe *pipe, void *td_ptr, size_t len, packet_len; uint32_t time; int ret = true; -#ifdef OHCI_DEBUG_PACKET - int i; - unsigned char *dbuf; -#endif if (pipe->type != USB_EP_TYPE_BULK) { printf("usb-ohci: Not a bulk pipe.\n"); @@ -691,22 +694,19 @@ static int ohci_transfer_bulk(struct usb_pipe *pipe, void *td_ptr, mb(); write_reg32(®s->bulk_head_ed, 0); -#ifdef OHCI_DEBUG_PACKET - if (datalen) { - len = ( datalen < 512 ) ? datalen : 512; - dbuf = data_phys; - dpprintf("Data :"); - for (i = 0; i < len; i++) { - if (i % 32 == 0) - dpprintf("\n\t"); - dpprintf("%02X ", dbuf[i]); - } - dpprintf("\n"); + if (le32_to_cpu(ed->headp) & EDA_HEADP_HALTED) { + printf("ED Halted\n"); + printf("%s: headp %08X tailp %08X next_td %08X attr %08X\n", __func__, + le32_to_cpu(ed->headp), le32_to_cpu(ed->tailp), + le32_to_cpu(ed->next_ed), le32_to_cpu(ed->attr)); + ed->headp &= ~cpu_to_le32(EDA_HEADP_HALTED); + mb(); + if (ret == USB_STALL) /* Call reset recovery */ + usb_msc_resetrecovery(pipe->dev); } -#endif end: - return ret; + return (ret > 0) ? true : false; } /* Populate the hcca intr region with periodic intr */ diff --git a/lib/libusb/usb-ohci.h b/lib/libusb/usb-ohci.h index 9b294cc..f4535fd 100644 --- a/lib/libusb/usb-ohci.h +++ b/lib/libusb/usb-ohci.h @@ -61,6 +61,8 @@ struct ohci_regs { #define EDA_HEADP_MASK (0xFFFFFFFC) #define EDA_HEADP_MASK_LE (cpu_to_le32(EDA_HEADP_MASK)) +#define EDA_HEADP_HALTED (0x1) +#define EDA_HEADP_CARRY (0x2) struct ohci_ed { uint32_t attr; @@ -79,12 +81,16 @@ struct ohci_ed { #define TDA_TOGGLE_DATA1 (0x03000000) #define TDA_CC (0xF << 28) +#define TDA_ERROR(x) ((x) * -1) + /* Table 4-7: Completion Codes */ const char *tda_cc_error[] = { +#define USB_NOERROR TDA_ERROR(0) "NOERROR", "CRC", "BITSTUFFING", "DATATOGGLEMISMATCH", +#define USB_STALL TDA_ERROR(4) "STALL", "DEVICENOTRESPONDING", "PIDCHECKFAILURE", |