diff options
| author | juhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2007-11-15 09:16:47 +0000 | 
|---|---|---|
| committer | juhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2007-11-15 09:16:47 +0000 | 
| commit | 7fcae4c7e6d4609af9eb6b6be00be4178083eb5d (patch) | |
| tree | 760751ea6ea11318c5af1d0c68e577aa193bc608 /target/linux/adm5120/files/drivers/usb/host | |
| parent | d895ddd832c3cd3b0007c276b1969d6e524d0d47 (diff) | |
[adm5120] more USB driver changes
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@9550 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/adm5120/files/drivers/usb/host')
4 files changed, 141 insertions, 214 deletions
| diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120-dbg.c b/target/linux/adm5120/files/drivers/usb/host/adm5120-dbg.c index debd42f1b..648576cc0 100644 --- a/target/linux/adm5120/files/drivers/usb/host/adm5120-dbg.c +++ b/target/linux/adm5120/files/drivers/usb/host/adm5120-dbg.c @@ -139,7 +139,7 @@ urb_print(struct admhcd *ahcd, struct urb * urb, char * str, int small)  static void admhc_dump_intr_mask(struct admhcd *ahcd, char *label, u32 mask,  		char **next, unsigned *size)  { -	admhc_dbg_sw(ahcd, next, size, "%s 0x%08x%s%s%s%s%s%s%s%s%s%s\n", +	admhc_dbg_sw(ahcd, next, size, "%s 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n",  		label,  		mask,  		(mask & ADMHC_INTR_INTA) ? " INTA" : "", @@ -150,6 +150,8 @@ static void admhc_dump_intr_mask(struct admhcd *ahcd, char *label, u32 mask,  		(mask & ADMHC_INTR_SO) ? " SO" : "",  		(mask & ADMHC_INTR_INSM) ? " INSM" : "",  		(mask & ADMHC_INTR_BABI) ? " BABI" : "", +		(mask & ADMHC_INTR_7) ? " !7!" : "", +		(mask & ADMHC_INTR_6) ? " !6!" : "",  		(mask & ADMHC_INTR_RESI) ? " RESI" : "",  		(mask & ADMHC_INTR_SOFI) ? " SOFI" : ""  		); diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120-hcd.c b/target/linux/adm5120/files/drivers/usb/host/adm5120-hcd.c index a5476fc07..48514d5cb 100644 --- a/target/linux/adm5120/files/drivers/usb/host/adm5120-hcd.c +++ b/target/linux/adm5120/files/drivers/usb/host/adm5120-hcd.c @@ -45,20 +45,21 @@  #include "../core/hcd.h"  #include "../core/hub.h" -#define DRIVER_VERSION	"v0.05" +#define DRIVER_VERSION	"v0.06"  #define DRIVER_AUTHOR	"Gabor Juhos <juhosg at openwrt.org>"  #define DRIVER_DESC	"ADMtek USB 1.1 Host Controller Driver"  /*-------------------------------------------------------------------------*/ -#define ADMHC_VERBOSE_DEBUG	/* not always helpful */ +#undef ADMHC_VERBOSE_DEBUG	/* not always helpful */  /* For initializing controller (mask in an HCFS mode too) */  #define	OHCI_CONTROL_INIT	OHCI_CTRL_CBSR  #define	ADMHC_INTR_INIT \  		( ADMHC_INTR_MIE | ADMHC_INTR_INSM | ADMHC_INTR_FATI \ -		| ADMHC_INTR_RESI | ADMHC_INTR_TDC | ADMHC_INTR_BABI ) +		| ADMHC_INTR_RESI | ADMHC_INTR_TDC | ADMHC_INTR_BABI \ +		| ADMHC_INTR_7 | ADMHC_INTR_6 )  /*-------------------------------------------------------------------------*/ @@ -346,6 +347,7 @@ static int admhc_get_frame_number(struct usb_hcd *hcd)  static void admhc_usb_reset(struct admhcd *ahcd)  { +	admhc_dbg(ahcd, "usb reset\n");  	ahcd->host_control = ADMHC_BUSS_RESET;  	admhc_writel(ahcd, ahcd->host_control, &ahcd->regs->host_control);  } @@ -359,6 +361,8 @@ admhc_shutdown(struct usb_hcd *hcd)  {  	struct admhcd *ahcd; +	admhc_dbg(ahcd, "shutdown\n"); +  	ahcd = hcd_to_admhcd(hcd);  	admhc_intr_disable(ahcd, ADMHC_INTR_MIE);  	admhc_dma_disable(ahcd); @@ -394,7 +398,7 @@ static void admhc_eds_cleanup(struct admhcd *ahcd)  	ahcd->ed_head = NULL;  } -#define ED_DUMMY_INFO	(ED_SPEED_FULL | ED_SKIP) +#define ED_DUMMY_INFO	0  static int admhc_eds_init(struct admhcd *ahcd)  { @@ -527,8 +531,8 @@ static int admhc_run(struct admhcd *ahcd)  		break;  	}  	admhc_writel(ahcd, ahcd->host_control, &ahcd->regs->host_control); -  	msleep(temp); +  	temp = admhc_read_rhdesc(ahcd);  	if (!(temp & ADMHC_RH_NPS)) {  		/* power down each port */ @@ -547,7 +551,7 @@ static int admhc_run(struct admhcd *ahcd)  			admhc_err(ahcd, "USB HC reset timed out!\n");  			return -1;  		} -		udelay (1); +		udelay(1);  	}  	/* enable HOST mode, before access any host specific register */ @@ -562,22 +566,10 @@ static int admhc_run(struct admhcd *ahcd)  	hcd->poll_rh = 1;  	hcd->uses_new_polling = 1; -#if 0 -	/* wake on ConnectStatusChange, matching external hubs */ -	admhc_writel(ahcd, RH_HS_DRWE, &ahcd->regs->roothub.status); -#else -	/* FIXME roothub_write_status (ahcd, ADMHC_RH_DRWE); */ -#endif - -	/* Choose the interrupts we care about now, others later on demand */ -	admhc_intr_ack(ahcd, ~0); -	admhc_intr_enable(ahcd, ADMHC_INTR_INIT); - -	admhc_writel(ahcd, ADMHC_RH_NPS | ADMHC_RH_LPSC, &ahcd->regs->rhdesc); -  	/* start controller operations */  	ahcd->host_control = ADMHC_BUSS_OPER;  	admhc_writel(ahcd, ahcd->host_control, &ahcd->regs->host_control); +	hcd->state = HC_STATE_RUNNING;  	temp = 20;  	while ((admhc_readl(ahcd, &ahcd->regs->host_control) @@ -590,12 +582,24 @@ static int admhc_run(struct admhcd *ahcd)  		mdelay(1);  	} -	hcd->state = HC_STATE_RUNNING; -	ahcd->next_statechange = jiffies + STATECHANGE_DELAY; +#if 0 +	/* FIXME */ +	/* wake on ConnectStatusChange, matching external hubs */ +	admhc_writel(ahcd, ADMHC_RH_DRWE, &ahcd->regs->rhdesc); +#endif + +	/* Choose the interrupts we care about now, others later on demand */ +	temp = ADMHC_INTR_INIT; +	admhc_intr_ack(ahcd, ~0); +	admhc_intr_enable(ahcd, temp); +	admhc_writel(ahcd, ADMHC_RH_NPS | ADMHC_RH_LPSC, &ahcd->regs->rhdesc); + +	ahcd->next_statechange = jiffies + STATECHANGE_DELAY;  	spin_unlock_irq(&ahcd->lock);  	mdelay(ADMHC_POTPGT); +	hcd->state = HC_STATE_RUNNING;  	return 0;  } @@ -611,13 +615,27 @@ static irqreturn_t admhc_irq(struct usb_hcd *hcd)   	u32 ints;  	ints = admhc_readl(ahcd, ®s->int_status); -	if (!(ints & ADMHC_INTR_INTA)) +	if (!(ints & ADMHC_INTR_INTA)) {  		/* no unmasked interrupt status is set */ +		admhc_err(ahcd, "spurious interrupt %08x\n", ints);  		return IRQ_NONE; +	}  	ints &= admhc_readl(ahcd, ®s->int_enable); -	if (!ints) +	if (!ints) { +		admhc_err(ahcd, "hardware irq problems?\n");  		return IRQ_NONE; +	} + +	if (ints & ADMHC_INTR_6) { +		admhc_err(ahcd, "unknown interrupt 6\n"); +		admhc_dump(ahcd, 0); +	} + +	if (ints & ADMHC_INTR_7) { +		admhc_err(ahcd, "unknown interrupt 7\n"); +		admhc_dump(ahcd, 0); +	}  	if (ints & ADMHC_INTR_FATI) {  		admhc_disable(ahcd); @@ -655,16 +673,17 @@ static irqreturn_t admhc_irq(struct usb_hcd *hcd)  		admhc_intr_ack(ahcd, ADMHC_INTR_RESI);  		hcd->poll_rh = 1;  		if (ahcd->autostop) { +			spin_lock(&ahcd->lock);  			admhc_rh_resume(ahcd); +			spin_unlock(&ahcd->lock);  		} else  			usb_hcd_resume_root_hub(hcd);  	}  	if (ints & ADMHC_INTR_TDC) { -		admhc_intr_ack(ahcd, ADMHC_INTR_TDC); +		admhc_vdbg(ahcd, "Transfer Descriptor Complete\n");  		if (HC_IS_RUNNING(hcd->state))  			admhc_intr_disable(ahcd, ADMHC_INTR_TDC); -		admhc_vdbg(ahcd, "Transfer Descriptor Complete\n");  		spin_lock(&ahcd->lock);  		admhc_td_complete(ahcd);  		spin_unlock(&ahcd->lock); @@ -674,15 +693,13 @@ static irqreturn_t admhc_irq(struct usb_hcd *hcd)  	if (ints & ADMHC_INTR_SO) {  		/* could track INTR_SO to reduce available PCI/... bandwidth */ -		admhc_vdbg(ahcd, "Schedule Overrun\n"); +		admhc_err(ahcd, "Schedule Overrun\n");  	}  	if (ints & ADMHC_INTR_SOFI) { -		admhc_intr_ack(ahcd, ADMHC_INTR_SOFI);  		spin_lock(&ahcd->lock);  		/* handle any pending ED removes */  		admhc_finish_unlinks(ahcd, admhc_frame_no(ahcd)); -		admhc_sof_refill(ahcd);  		spin_unlock(&ahcd->lock);  	} diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120-q.c b/target/linux/adm5120/files/drivers/usb/host/adm5120-q.c index a9e002e7d..c96c327e8 100644 --- a/target/linux/adm5120/files/drivers/usb/host/adm5120-q.c +++ b/target/linux/adm5120/files/drivers/usb/host/adm5120-q.c @@ -90,6 +90,8 @@ static struct ed *ed_create(struct admhcd *ahcd, unsigned int type, u32 info)  		break;  	} +	info |= ED_SKIP; +  	ed->dummy = td;  	ed->state = ED_NEW;  	ed->type = type; @@ -112,10 +114,8 @@ err:  static struct ed *ed_get(struct admhcd *ahcd,	struct usb_host_endpoint *ep,  	struct usb_device *udev, unsigned int pipe, int interval)  { -	struct ed		*ed; -	unsigned long		flags; +	struct ed *ed; -	spin_lock_irqsave(&ahcd->lock, flags);  	ed = ep->hcpriv;  	if (!ed) {  		u32		info; @@ -133,11 +133,33 @@ static struct ed *ed_get(struct admhcd *ahcd,	struct usb_host_endpoint *ep,  		if (ed)  			ep->hcpriv = ed;  	} -	spin_unlock_irqrestore(&ahcd->lock, flags);  	return ed;  } +static void ed_next_urb(struct admhcd *ahcd, struct ed *ed) +{ +	struct urb_priv *up; +	u32 carry; + +	up = list_entry(ed->urb_pending.next, struct urb_priv, pending); +	list_del(&up->pending); + +	ed->urb_active = up; +	ed->state = ED_OPER; + +#ifdef ADMHC_VERBOSE_DEBUG +	urb_print(ahcd, up->urb, "NEXT", 0); +	admhc_dump_ed(ahcd, " ", ed, 0); +#endif + +	up->td[up->td_cnt-1]->hwNextTD = cpu_to_hc32(ahcd, ed->dummy->td_dma); + +	carry = hc32_to_cpup(ahcd, &ed->hwHeadP) & ED_C; +	ed->hwHeadP = cpu_to_hc32(ahcd, up->td[0]->td_dma | carry); +	ed->hwINFO &= ~cpu_to_hc32(ahcd, ED_SKIP); +} +  /* link an ed into the HC chain */  static int ed_schedule(struct admhcd *ahcd, struct ed *ed)  { @@ -146,37 +168,43 @@ static int ed_schedule(struct admhcd *ahcd, struct ed *ed)  	if (admhcd_to_hcd(ahcd)->state == HC_STATE_QUIESCING)  		return -EAGAIN; -	if (ed->state != ED_NEW) -		return 0; +	if (ed->state == ED_NEW) { +		ed->state = ED_IDLE; -	admhc_dump_ed(ahcd, "ED-SCHED", ed, 0); - -	ed->state = ED_IDLE; +		old_tail = ahcd->ed_tails[ed->type]; -	ed->hwINFO &= ~cpu_to_hc32(ahcd, ED_SKIP); +		ed->ed_next = old_tail->ed_next; +		if (ed->ed_next) { +			ed->ed_next->ed_prev = ed; +			ed->hwNextED = cpu_to_hc32(ahcd, ed->ed_next->dma); +		} +		ed->ed_prev = old_tail; -	old_tail = ahcd->ed_tails[ed->type]; +		old_tail->ed_next = ed; +		old_tail->hwNextED = cpu_to_hc32(ahcd, ed->dma); -	ed->ed_next = old_tail->ed_next; -	if (ed->ed_next) { -		ed->ed_next->ed_prev = ed; -		ed->hwNextED = cpu_to_hc32(ahcd, ed->ed_next->dma); +		ahcd->ed_tails[ed->type] = ed; +		ed->hwINFO &= ~cpu_to_hc32(ahcd, ED_SKIP);  	} -	ed->ed_prev = old_tail; -	old_tail->ed_next = ed; -	old_tail->hwNextED = cpu_to_hc32(ahcd, ed->dma); - -	ahcd->ed_tails[ed->type] = ed; +#ifdef ADMHC_VERBOSE_DEBUG +	admhc_dump_ed(ahcd, "ED-SCHED", ed, 0); +#endif -	admhc_intr_enable(ahcd, ADMHC_INTR_SOFI); +	if (!ed->urb_active) { +		ed_next_urb(ahcd, ed); +		admhc_dma_enable(ahcd); +	}  	return 0;  }  static void ed_deschedule(struct admhcd *ahcd, struct ed *ed)  { + +#ifdef ADMHC_VERBOSE_DEBUG  	admhc_dump_ed(ahcd, "ED-DESCHED", ed, 0); +#endif  	/* remove this ED from the HC list */  	ed->ed_prev->hwNextED = ed->hwNextED; @@ -197,16 +225,14 @@ static void ed_deschedule(struct admhcd *ahcd, struct ed *ed)  static void ed_start_deschedule(struct admhcd *ahcd, struct ed *ed)  { + +#ifdef ADMHC_VERBOSE_DEBUG  	admhc_dump_ed(ahcd, "ED-UNLINK", ed, 0); +#endif  	ed->hwINFO |= cpu_to_hc32(ahcd, ED_SKIP); -  	ed->state = ED_UNLINK; -	/* add this ED into the remove list */ -	ed->ed_rm_next = ahcd->ed_rm_list; -	ahcd->ed_rm_list = ed; -  	/* SOF interrupt might get delayed; record the frame counter value that  	 * indicates when the HC isn't looking at it, so concurrent unlinks  	 * behave.  frame_no wraps every 2^16 msec, and changes right before @@ -214,7 +240,6 @@ static void ed_start_deschedule(struct admhcd *ahcd, struct ed *ed)  	 */  	ed->tick = admhc_frame_no(ahcd) + 1; -	/* enable SOF interrupt */  	admhc_intr_enable(ahcd, ADMHC_INTR_SOFI);  } @@ -229,9 +254,9 @@ static void td_fill(struct admhcd *ahcd, u32 info, dma_addr_t data, int len,  	u32 cbl = 0;  	if (up->td_idx >= up->td_cnt) { -		admhc_dbg(ahcd, "td_fill error, idx=%d, cnt=%d\n", up->td_idx, +		admhc_err(ahcd, "td_fill error, idx=%d, cnt=%d\n", up->td_idx,  				up->td_cnt); -		return; +		BUG();  	}  	td = up->td[up->td_idx]; @@ -239,9 +264,7 @@ static void td_fill(struct admhcd *ahcd, u32 info, dma_addr_t data, int len,  	if (!len)  		data = 0; -#if 1  	if (up->td_idx == up->td_cnt-1) -#endif  		cbl |= TD_IE;  	if (data) @@ -446,7 +469,10 @@ static int td_done(struct admhcd *ahcd, struct urb *urb, struct td *td)  	 * might not be reported as errors.  	 */  	} else { + +#ifdef ADMHC_VERBOSE_DEBUG  		admhc_dump_td(ahcd, "td_done", td); +#endif  		/* count all non-empty packets except control SETUP packet */  		if ((type != PIPE_CONTROL || td->index != 0) && dbp != 0) { @@ -459,122 +485,7 @@ static int td_done(struct admhcd *ahcd, struct urb *urb, struct td *td)  /*-------------------------------------------------------------------------*/ -static inline struct td * -ed_halted(struct admhcd *ahcd, struct td *td, int cc, struct td *rev) -{ -#if 0 -	struct urb		*urb = td->urb; -	struct ed		*ed = td->ed; -	struct list_head	*tmp = td->td_list.next; -	__hc32			toggle = ed->hwHeadP & cpu_to_hc32 (ahcd, ED_C); - -	admhc_dump_ed(ahcd, "ed halted", td->ed, 1); -	/* clear ed halt; this is the td that caused it, but keep it inactive -	 * until its urb->complete() has a chance to clean up. -	 */ -	ed->hwINFO |= cpu_to_hc32 (ahcd, ED_SKIP); -	wmb (); -	ed->hwHeadP &= ~cpu_to_hc32 (ahcd, ED_H); - -	/* put any later tds from this urb onto the donelist, after 'td', -	 * order won't matter here: no errors, and nothing was transferred. -	 * also patch the ed so it looks as if those tds completed normally. -	 */ -	while (tmp != &ed->td_list) { -		struct td	*next; -		__hc32		info; - -		next = list_entry(tmp, struct td, td_list); -		tmp = next->td_list.next; - -		if (next->urb != urb) -			break; - -		/* NOTE: if multi-td control DATA segments get supported, -		 * this urb had one of them, this td wasn't the last td -		 * in that segment (TD_R clear), this ed halted because -		 * of a short read, _and_ URB_SHORT_NOT_OK is clear ... -		 * then we need to leave the control STATUS packet queued -		 * and clear ED_SKIP. -		 */ -		info = next->hwINFO; -#if 0		/* FIXME */ -		info |= cpu_to_hc32 (ahcd, TD_DONE); -		info &= ~cpu_to_hc32 (ahcd, TD_CC); -#endif -		next->hwINFO = info; - -		next->next_dl_td = rev; -		rev = next; - -		ed->hwHeadP = next->hwNextTD | toggle; -	} - -	/* help for troubleshooting:  report anything that -	 * looks odd ... that doesn't include protocol stalls -	 * (or maybe some other things) -	 */ -	switch (cc) { -	case TD_CC_DATAUNDERRUN: -		if ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0) -			break; -		/* fallthrough */ -	case TD_CC_STALL: -		if (usb_pipecontrol (urb->pipe)) -			break; -		/* fallthrough */ -	default: -		admhc_dbg (ahcd, -			"urb %p path %s ep%d%s %08x cc %d --> status %d\n", -			urb, urb->dev->devpath, -			usb_pipeendpoint (urb->pipe), -			usb_pipein (urb->pipe) ? "in" : "out", -			hc32_to_cpu(ahcd, td->hwINFO), -			cc, cc_to_error [cc]); -	} - -	return rev; -#else -	return NULL; -#endif -} - -/*-------------------------------------------------------------------------*/ - -static int ed_next_urb(struct admhcd *ahcd, struct ed *ed) -{ -	struct urb_priv *up; -	u32 carry; - -	if (ed->state != ED_IDLE) -		return 1; - -	if (ed->urb_active) -		return 1; - -	if (list_empty(&ed->urb_pending)) -		return 0; - -	up = list_entry(ed->urb_pending.next, struct urb_priv, pending); -	list_del(&up->pending); -	ed->urb_active = up; -	ed->state = ED_OPER; - -#ifdef ADMHC_VERBOSE_DEBUG -	urb_print(ahcd, up->urb, "NEXT", 0); -	admhc_dump_ed(ahcd, " ", ed, 0); -#endif - -	up->td[up->td_cnt-1]->hwNextTD = cpu_to_hc32(ahcd, ed->dummy->td_dma); - -	carry = hc32_to_cpup(ahcd, &ed->hwHeadP) & ED_C; -	ed->hwHeadP = cpu_to_hc32(ahcd, up->td[0]->td_dma | carry); -	ed->hwINFO &= ~cpu_to_hc32(ahcd, ED_SKIP); - -	return 1; -} - -static void ed_update(struct admhcd *ahcd, struct ed *ed, int partial) +static void ed_update(struct admhcd *ahcd, struct ed *ed, int force)  {  	struct urb_priv *up;  	struct urb *urb; @@ -588,8 +499,8 @@ static void ed_update(struct admhcd *ahcd, struct ed *ed, int partial)  #ifdef ADMHC_VERBOSE_DEBUG  	urb_print(ahcd, urb, "UPDATE", 0); -#endif  	admhc_dump_ed(ahcd, "ED-UPDATE", ed, 1); +#endif  	cc = TD_CC_NOERROR;  	for (; up->td_idx < up->td_cnt; up->td_idx++) { @@ -611,7 +522,7 @@ static void ed_update(struct admhcd *ahcd, struct ed *ed, int partial)  		}  	} -	if ((up->td_idx != up->td_cnt) && (!partial)) +	if ((up->td_idx != up->td_cnt) && (!force))  		/* the URB is not completed yet */  		return; @@ -637,68 +548,65 @@ static void ed_update(struct admhcd *ahcd, struct ed *ed, int partial)  static void admhc_td_complete(struct admhcd *ahcd)  {  	struct ed *ed; +	int more = 0;  	for (ed = ahcd->ed_head; ed; ed = ed->ed_next) {  		if (ed->state != ED_OPER)  			continue; -		if (hc32_to_cpup(ahcd, &ed->hwINFO) & ED_SKIP) +		if (hc32_to_cpup(ahcd, &ed->hwHeadP) & ED_H) { +			admhc_dump_ed(ahcd, "ed halted", ed, 1); +			ed_update(ahcd, ed, 1); +			ed->hwHeadP &= ~cpu_to_hc32(ahcd, ED_H); +		} else +			ed_update(ahcd, ed, 0); + +		if (ed->urb_active) { +			more = 1;  			continue; +		} -		if (hc32_to_cpup(ahcd, &ed->hwHeadP) & ED_H) { -			/* TODO */ +		if (!(list_empty(&ed->urb_pending))) { +			more = 1; +			ed_next_urb(ahcd, ed);  			continue;  		} -		ed_update(ahcd, ed, 0); +		ed_start_deschedule(ahcd, ed);  	} + +	if (!more) +		admhc_dma_disable(ahcd); +  }  /* there are some urbs/eds to unlink; called in_irq(), with HCD locked */  static void admhc_finish_unlinks(struct admhcd *ahcd, u16 tick)  {  	struct ed *ed; +	int more = 0;  	for (ed = ahcd->ed_head; ed; ed = ed->ed_next) {  		if (ed->state != ED_UNLINK)  			continue;  		if (likely(HC_IS_RUNNING(admhcd_to_hcd(ahcd)->state))) -			if (tick_before(tick, ed->tick)) +			if (tick_before(tick, ed->tick)) { +				more = 1;  				continue; +			}  		/* process partial status */ -		ed_update(ahcd, ed, 1); -	} -} - -static void admhc_sof_refill(struct admhcd *ahcd) -{ -	struct ed *ed; -	int disable_dma = 1; - -	for (ed = ahcd->ed_head; ed; ed = ed->ed_next) { - -		if (hc32_to_cpup(ahcd, &ed->hwHeadP) & ED_H) { +		if (ed->urb_active)  			ed_update(ahcd, ed, 1); -			ed->hwHeadP &= ~cpu_to_hc32 (ahcd, ED_H); -		} -		if (ed_next_urb(ahcd, ed)) { -			disable_dma = 0; -		} else { -			struct ed *tmp; -			tmp = ed->ed_prev; +		if (list_empty(&ed->urb_pending))  			ed_deschedule(ahcd, ed); -			ed = tmp; -		} +		else +			ed_schedule(ahcd, ed);  	} -	if (disable_dma) { -		admhc_intr_disable(ahcd, ADMHC_INTR_SOFI); -		admhc_dma_disable(ahcd); -	} else { -		admhc_intr_enable(ahcd, ADMHC_INTR_SOFI); -		admhc_dma_enable(ahcd); -	} +	if (!more) +		if (likely(HC_IS_RUNNING(admhcd_to_hcd(ahcd)->state))) +			admhc_intr_disable(ahcd, ADMHC_INTR_SOFI);  } diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120.h b/target/linux/adm5120/files/drivers/usb/host/adm5120.h index a682856eb..72740783b 100644 --- a/target/linux/adm5120/files/drivers/usb/host/adm5120.h +++ b/target/linux/adm5120/files/drivers/usb/host/adm5120.h @@ -65,7 +65,6 @@ struct ed {  	/* host's view of schedule */  	struct ed		*ed_next;	/* on schedule list */  	struct ed		*ed_prev;	/* for non-interrupt EDs */ -	struct ed		*ed_rm_next;	/* on rm list */  	/* create --> IDLE --> OPER --> ... --> IDLE --> destroy  	 * usually:  OPER --> UNLINK --> (IDLE | OPER) --> ... @@ -262,6 +261,8 @@ struct admhcd_regs {   */  #define ADMHC_INTR_SOFI	(1 << 4)	/* start of frame */  #define ADMHC_INTR_RESI	(1 << 5)	/* resume detected */ +#define ADMHC_INTR_6	(1 << 6)	/* unknown */ +#define ADMHC_INTR_7	(1 << 7)	/* unknown */  #define ADMHC_INTR_BABI	(1 << 8)	/* babble detected */  #define ADMHC_INTR_INSM	(1 << 9)	/* root hub status change */  #define ADMHC_INTR_SO	(1 << 10)	/* scheduling overrun */ @@ -381,8 +382,7 @@ struct admhcd {  	struct ed		*ed_head;  	struct ed		*ed_tails[4]; -	struct ed		*ed_rm_list;	/* to be removed */ -	struct ed		*periodic[NUM_INTS];	/* shadow int_table */ +//	struct ed		*periodic[NUM_INTS];	/* shadow int_table */  #if 0	/* TODO: remove? */  	/* | 
