diff options
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
| -rw-r--r-- | drivers/usb/host/ehci-hcd.c | 75 | 
1 files changed, 25 insertions, 50 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 5726cb144ab..b12b97d2cca 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -302,6 +302,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)  static void end_unlink_async(struct ehci_hcd *ehci);  static void unlink_empty_async(struct ehci_hcd *ehci); +static void unlink_empty_async_suspended(struct ehci_hcd *ehci);  static void ehci_work(struct ehci_hcd *ehci);  static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);  static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); @@ -481,6 +482,9 @@ static int ehci_init(struct usb_hcd *hcd)  	 * periodic_size can shrink by USBCMD update if hcc_params allows.  	 */  	ehci->periodic_size = DEFAULT_I_TDPS; +	INIT_LIST_HEAD(&ehci->async_unlink); +	INIT_LIST_HEAD(&ehci->async_idle); +	INIT_LIST_HEAD(&ehci->intr_unlink);  	INIT_LIST_HEAD(&ehci->intr_qh_list);  	INIT_LIST_HEAD(&ehci->cached_itd_list);  	INIT_LIST_HEAD(&ehci->cached_sitd_list); @@ -748,7 +752,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)  		/* guard against (alleged) silicon errata */  		if (cmd & CMD_IAAD)  			ehci_dbg(ehci, "IAA with IAAD still set?\n"); -		if (ehci->async_iaa) +		if (ehci->iaa_in_progress)  			COUNT(ehci->stats.iaa);  		end_unlink_async(ehci);  	} @@ -756,7 +760,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)  	/* remote wakeup [4.3.1] */  	if (status & STS_PCD) {  		unsigned	i = HCS_N_PORTS (ehci->hcs_params); -		u32		ppcd = 0; +		u32		ppcd = ~0;  		/* kick root hub later */  		pcd_status = status; @@ -773,7 +777,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)  			int pstatus;  			/* leverage per-port change bits feature */ -			if (ehci->has_ppcd && !(ppcd & (1 << i))) +			if (!(ppcd & (1 << i)))  				continue;  			pstatus = ehci_readl(ehci,  					 &ehci->regs->port_status[i]); @@ -895,17 +899,24 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)  	if (rc)  		goto done; -	switch (usb_pipetype (urb->pipe)) { -	// case PIPE_CONTROL: -	// case PIPE_BULK: -	default: +	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { +		/* +		 * We don't expedite dequeue for isochronous URBs. +		 * Just wait until they complete normally or their +		 * time slot expires. +		 */ +	} else {  		qh = (struct ehci_qh *) urb->hcpriv; -		if (!qh) -			break; +		qh->exception = 1;  		switch (qh->qh_state) {  		case QH_STATE_LINKED: +			if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) +				start_unlink_intr(ehci, qh); +			else +				start_unlink_async(ehci, qh); +			break;  		case QH_STATE_COMPLETING: -			start_unlink_async(ehci, qh); +			qh->dequeue_during_giveback = 1;  			break;  		case QH_STATE_UNLINK:  		case QH_STATE_UNLINK_WAIT: @@ -916,33 +927,6 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)  			qh_completions(ehci, qh);  			break;  		} -		break; - -	case PIPE_INTERRUPT: -		qh = (struct ehci_qh *) urb->hcpriv; -		if (!qh) -			break; -		switch (qh->qh_state) { -		case QH_STATE_LINKED: -		case QH_STATE_COMPLETING: -			start_unlink_intr(ehci, qh); -			break; -		case QH_STATE_IDLE: -			qh_completions (ehci, qh); -			break; -		default: -			ehci_dbg (ehci, "bogus qh %p state %d\n", -					qh, qh->qh_state); -			goto done; -		} -		break; - -	case PIPE_ISOCHRONOUS: -		// itd or sitd ... - -		// wait till next completion, do it then. -		// completion irqs can wait up to 1024 msec, -		break;  	}  done:  	spin_unlock_irqrestore (&ehci->lock, flags); @@ -983,6 +967,7 @@ rescan:  		goto done;  	} +	qh->exception = 1;  	if (ehci->rh_state < EHCI_RH_RUNNING)  		qh->qh_state = QH_STATE_IDLE;  	switch (qh->qh_state) { @@ -1051,13 +1036,12 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)  		usb_settoggle(qh->dev, epnum, is_out, 0);  		if (!list_empty(&qh->qtd_list)) {  			WARN_ONCE(1, "clear_halt for a busy endpoint\n"); -		} else if (qh->qh_state == QH_STATE_LINKED || -				qh->qh_state == QH_STATE_COMPLETING) { - +		} else {  			/* The toggle value in the QH can't be updated  			 * while the QH is active.  Unlink it now;  			 * re-linking will call qh_refresh().  			 */ +			qh->exception = 1;  			if (eptype == USB_ENDPOINT_XFER_BULK)  				start_unlink_async(ehci, qh);  			else @@ -1250,11 +1234,6 @@ MODULE_LICENSE ("GPL");  #define PLATFORM_DRIVER		ehci_hcd_sh_driver  #endif -#ifdef CONFIG_USB_EHCI_HCD_OMAP -#include "ehci-omap.c" -#define        PLATFORM_DRIVER         ehci_hcd_omap_driver -#endif -  #ifdef CONFIG_PPC_PS3  #include "ehci-ps3.c"  #define	PS3_SYSTEM_BUS_DRIVER	ps3_ehci_driver @@ -1290,11 +1269,6 @@ MODULE_LICENSE ("GPL");  #define PLATFORM_DRIVER		ehci_octeon_driver  #endif -#ifdef CONFIG_ARCH_VT8500 -#include "ehci-vt8500.c" -#define	PLATFORM_DRIVER		vt8500_ehci_driver -#endif -  #ifdef CONFIG_PLAT_SPEAR  #include "ehci-spear.c"  #define PLATFORM_DRIVER		spear_ehci_hcd_driver @@ -1344,6 +1318,7 @@ MODULE_LICENSE ("GPL");  	!IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \  	!IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \  	!IS_ENABLED(CONFIG_USB_EHCI_MXC) && \ +	!IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \  	!defined(PLATFORM_DRIVER) && \  	!defined(PS3_SYSTEM_BUS_DRIVER) && \  	!defined(OF_PLATFORM_DRIVER) && \  |