#include "../core/hcd.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_DESC "ADMtek USB 1.1 Host Controller Driver"
/* number of packets from URB */
td_cnt = urb->number_of_packets;
break;
- default:
- /* paranoia */
- admhc_err(ahcd, "bad EP type %d", ed->type);
- return -EINVAL;
}
urb_priv = urb_priv_alloc(ahcd, td_cnt, mem_flags);
#ifdef ADMHC_VERBOSE_DEBUG
admhc_dump_ed(ahcd, "admhc_urb_enqueue", urb_priv->ed, 1);
#endif
+
fail0:
spin_unlock(&urb->lock);
fail:
*/
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);
wmb();
ed->state = ED_UNLINK;
*/
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_deschedule(ahcd, ed);
last = &ed->ed_rm_next;
continue;
}
-
+#if 0
if (!list_empty(&ed->td_list)) {
struct td *td;
u32 head;
if (td->td_dma != head)
goto skip_ed;
}
+#endif
}
/* reentrancy: if we drop the schedule lock, someone might
*prev = td->hwNextTD | savebits;
/* 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);
/* if URB is done, clean up */
ed->state = ED_IDLE;
ed->hwHeadP &= ~cpu_to_hc32(ahcd, ED_H);
ed->hwNextED = 0;
- wmb ();
+ wmb();
ed->hwINFO &= ~cpu_to_hc32(ahcd, ED_SKIP | ED_DEQUEUE);
/* but if there's work queued, reschedule */
}
+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)
{
return ((hc32_to_cpup(ahcd, &ed->hwHeadP) & ED_H) == ED_H);
struct list_head *entry,*tmp;
#ifdef ADMHC_VERBOSE_DEBUG
- admhc_dump_ed(ahcd, "UPDATE", ed, 0);
+ admhc_dump_ed(ahcd, "UPDATE", ed, 1);
#endif
list_for_each_safe(entry, tmp, &ed->td_list) {
if (is_ed_halted(ahcd, ed) && is_td_halted(ahcd, ed, td))
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 (urb_priv->td_idx == urb_priv->td_cnt)
finish_urb(ahcd, urb);