[adm5120] more USB driver fixes, now it passes usbtests 1-14

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@9599 3c298f89-4303-0410-b956-a3cf2f4a3e73
master
Gabor Juhos 2007-11-26 08:49:58 +00:00
parent 4e482e0b58
commit 53fcb443df
2 changed files with 30 additions and 9 deletions

View File

@ -45,7 +45,7 @@
#include "../core/hcd.h" #include "../core/hcd.h"
#include "../core/hub.h" #include "../core/hub.h"
#define DRIVER_VERSION "v0.10.1" #define DRIVER_VERSION "v0.14.0"
#define DRIVER_AUTHOR "Gabor Juhos <juhosg at openwrt.org>" #define DRIVER_AUTHOR "Gabor Juhos <juhosg at openwrt.org>"
#define DRIVER_DESC "ADMtek USB 1.1 Host Controller Driver" #define DRIVER_DESC "ADMtek USB 1.1 Host Controller Driver"
@ -142,10 +142,6 @@ static int admhc_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *ep,
/* number of packets from URB */ /* number of packets from URB */
td_cnt = urb->number_of_packets; td_cnt = urb->number_of_packets;
break; break;
default:
/* paranoia */
admhc_err(ahcd, "bad EP type %d", ed->type);
return -EINVAL;
} }
urb_priv = urb_priv_alloc(ahcd, td_cnt, mem_flags); urb_priv = urb_priv_alloc(ahcd, td_cnt, mem_flags);
@ -207,6 +203,7 @@ static int admhc_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *ep,
#ifdef ADMHC_VERBOSE_DEBUG #ifdef ADMHC_VERBOSE_DEBUG
admhc_dump_ed(ahcd, "admhc_urb_enqueue", urb_priv->ed, 1); admhc_dump_ed(ahcd, "admhc_urb_enqueue", urb_priv->ed, 1);
#endif #endif
fail0: fail0:
spin_unlock(&urb->lock); spin_unlock(&urb->lock);
fail: fail:

View File

@ -231,6 +231,11 @@ static void periodic_unlink (struct admhcd *ahcd, struct ed *ed)
*/ */
static void ed_deschedule(struct admhcd *ahcd, struct ed *ed) static void ed_deschedule(struct admhcd *ahcd, struct ed *ed)
{ {
#ifdef ADMHC_VERBOSE_DEBUG
admhc_dump_ed(ahcd, "ED-DESCHED", ed, 1);
#endif
ed->hwINFO |= cpu_to_hc32(ahcd, ED_SKIP); ed->hwINFO |= cpu_to_hc32(ahcd, ED_SKIP);
wmb(); wmb();
ed->state = ED_UNLINK; ed->state = ED_UNLINK;
@ -333,6 +338,11 @@ static struct ed *ed_get(struct admhcd *ahcd, struct usb_host_endpoint *ep,
*/ */
static void start_ed_unlink(struct admhcd *ahcd, struct ed *ed) static void start_ed_unlink(struct admhcd *ahcd, struct ed *ed)
{ {
#ifdef ADMHC_VERBOSE_DEBUG
admhc_dump_ed(ahcd, "ED-UNLINK", ed, 1);
#endif
ed->hwINFO |= cpu_to_hc32(ahcd, ED_DEQUEUE); ed->hwINFO |= cpu_to_hc32(ahcd, ED_DEQUEUE);
ed_deschedule(ahcd, ed); ed_deschedule(ahcd, ed);
@ -735,7 +745,7 @@ skip_ed:
last = &ed->ed_rm_next; last = &ed->ed_rm_next;
continue; continue;
} }
#if 0
if (!list_empty(&ed->td_list)) { if (!list_empty(&ed->td_list)) {
struct td *td; struct td *td;
u32 head; u32 head;
@ -749,6 +759,7 @@ skip_ed:
if (td->td_dma != head) if (td->td_dma != head)
goto skip_ed; goto skip_ed;
} }
#endif
} }
/* reentrancy: if we drop the schedule lock, someone might /* reentrancy: if we drop the schedule lock, someone might
@ -793,7 +804,9 @@ rescan_this:
*prev = td->hwNextTD | savebits; *prev = td->hwNextTD | savebits;
/* HC may have partly processed this TD */ /* HC may have partly processed this TD */
urb_print(ahcd, urb, "PARTIAL", 1); #ifdef ADMHC_VERBOSE_DEBUG
urb_print(ahcd, urb, "PARTIAL", 0);
#endif
td_done(ahcd, urb, td); td_done(ahcd, urb, td);
/* if URB is done, clean up */ /* if URB is done, clean up */
@ -865,6 +878,14 @@ static void ed_unhalt(struct admhcd *ahcd, struct ed *ed, struct urb *urb)
} }
static void ed_intr_refill(struct admhcd *ahcd, struct ed *ed)
{
__hc32 toggle = ed->hwHeadP & cpu_to_hc32(ahcd, ED_C);
ed->hwHeadP = ed->hwTailP | toggle;
}
static inline int is_ed_halted(struct admhcd *ahcd, struct ed *ed) static inline int is_ed_halted(struct admhcd *ahcd, struct ed *ed)
{ {
return ((hc32_to_cpup(ahcd, &ed->hwHeadP) & ED_H) == ED_H); return ((hc32_to_cpup(ahcd, &ed->hwHeadP) & ED_H) == ED_H);
@ -882,7 +903,7 @@ static void ed_update(struct admhcd *ahcd, struct ed *ed)
struct list_head *entry,*tmp; struct list_head *entry,*tmp;
#ifdef ADMHC_VERBOSE_DEBUG #ifdef ADMHC_VERBOSE_DEBUG
admhc_dump_ed(ahcd, "UPDATE", ed, 0); admhc_dump_ed(ahcd, "UPDATE", ed, 1);
#endif #endif
list_for_each_safe(entry, tmp, &ed->td_list) { list_for_each_safe(entry, tmp, &ed->td_list) {
@ -899,6 +920,9 @@ static void ed_update(struct admhcd *ahcd, struct ed *ed)
if (is_ed_halted(ahcd, ed) && is_td_halted(ahcd, ed, td)) if (is_ed_halted(ahcd, ed) && is_td_halted(ahcd, ed, td))
ed_unhalt(ahcd, ed, urb); ed_unhalt(ahcd, ed, urb);
if (ed->type == PIPE_INTERRUPT)
ed_intr_refill(ahcd,ed);
/* If all this urb's TDs are done, call complete() */ /* If all this urb's TDs are done, call complete() */
if (urb_priv->td_idx == urb_priv->td_cnt) if (urb_priv->td_idx == urb_priv->td_cnt)
finish_urb(ahcd, urb); finish_urb(ahcd, urb);