diff options
| author | Olof Johansson <olof@lixom.net> | 2013-02-12 15:08:21 -0800 | 
|---|---|---|
| committer | Olof Johansson <olof@lixom.net> | 2013-02-12 15:08:21 -0800 | 
| commit | 2cb6a0708e6680f0b8e6f3ab6b0a46d1c19d8b39 (patch) | |
| tree | b81bc4cc720e6a86498de1edc675e24845e611e0 /drivers/usb/host | |
| parent | 78d9b8055b9aaf53ced11fc15728df31610a21e9 (diff) | |
| parent | 836dc9e3fbbab0c30aa6e664417225f5c1fb1c39 (diff) | |
| download | olio-linux-3.10-2cb6a0708e6680f0b8e6f3ab6b0a46d1c19d8b39.tar.xz olio-linux-3.10-2cb6a0708e6680f0b8e6f3ab6b0a46d1c19d8b39.zip  | |
Merge tag 'v3.8-rc7' into next/boards
Linux 3.8-rc7
Diffstat (limited to 'drivers/usb/host')
| -rw-r--r-- | drivers/usb/host/ehci-hcd.c | 1 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-hub.c | 9 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-q.c | 50 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-sched.c | 9 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-timer.c | 29 | ||||
| -rw-r--r-- | drivers/usb/host/pci-quirks.c | 1 | ||||
| -rw-r--r-- | drivers/usb/host/uhci-hub.c | 3 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-ring.c | 13 | 
8 files changed, 73 insertions, 42 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 09537b2f100..b416a3fc995 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -797,6 +797,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)  			ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);  			set_bit(i, &ehci->resuming_ports);  			ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); +			usb_hcd_start_port_resume(&hcd->self, i);  			mod_timer(&hcd->rh_timer, ehci->reset_done[i]);  		}  	} diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 4ccb97c0678..4d3b294f203 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -649,7 +649,11 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)  			status = STS_PCD;  		}  	} -	/* FIXME autosuspend idle root hubs */ + +	/* If a resume is in progress, make sure it can finish */ +	if (ehci->resuming_ports) +		mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(25)); +  	spin_unlock_irqrestore (&ehci->lock, flags);  	return status ? retval : 0;  } @@ -851,6 +855,7 @@ static int ehci_hub_control (  				/* resume signaling for 20 msec */  				ehci->reset_done[wIndex] = jiffies  						+ msecs_to_jiffies(20); +				usb_hcd_start_port_resume(&hcd->self, wIndex);  				/* check the port again */  				mod_timer(&ehci_to_hcd(ehci)->rh_timer,  						ehci->reset_done[wIndex]); @@ -862,6 +867,7 @@ static int ehci_hub_control (  				clear_bit(wIndex, &ehci->suspended_ports);  				set_bit(wIndex, &ehci->port_c_suspend);  				ehci->reset_done[wIndex] = 0; +				usb_hcd_end_port_resume(&hcd->self, wIndex);  				/* stop resume signaling */  				temp = ehci_readl(ehci, status_reg); @@ -950,6 +956,7 @@ static int ehci_hub_control (  			ehci->reset_done[wIndex] = 0;  			if (temp & PORT_PE)  				set_bit(wIndex, &ehci->port_c_suspend); +			usb_hcd_end_port_resume(&hcd->self, wIndex);  		}  		if (temp & PORT_OC) diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 3d989028c83..fd252f0cfb3 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1197,17 +1197,26 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)  	if (ehci->async_iaa || ehci->async_unlinking)  		return; -	/* Do all the waiting QHs at once */ -	ehci->async_iaa = ehci->async_unlink; -	ehci->async_unlink = NULL; -  	/* If the controller isn't running, we don't have to wait for it */  	if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) { + +		/* Do all the waiting QHs */ +		ehci->async_iaa = ehci->async_unlink; +		ehci->async_unlink = NULL; +  		if (!nested)		/* Avoid recursion */  			end_unlink_async(ehci);  	/* Otherwise start a new IAA cycle */  	} else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) { +		struct ehci_qh		*qh; + +		/* Do only the first waiting QH (nVidia bug?) */ +		qh = ehci->async_unlink; +		ehci->async_iaa = qh; +		ehci->async_unlink = qh->unlink_next; +		qh->unlink_next = NULL; +  		/* Make sure the unlinks are all visible to the hardware */  		wmb(); @@ -1255,34 +1264,35 @@ static void end_unlink_async(struct ehci_hcd *ehci)  	}  } +static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh); +  static void unlink_empty_async(struct ehci_hcd *ehci)  { -	struct ehci_qh		*qh, *next; -	bool			stopped = (ehci->rh_state < EHCI_RH_RUNNING); +	struct ehci_qh		*qh; +	struct ehci_qh		*qh_to_unlink = NULL;  	bool			check_unlinks_later = false; +	int			count = 0; -	/* Unlink all the async QHs that have been empty for a timer cycle */ -	next = ehci->async->qh_next.qh; -	while (next) { -		qh = next; -		next = qh->qh_next.qh; - +	/* Find the last async QH which has been empty for a timer cycle */ +	for (qh = ehci->async->qh_next.qh; qh; qh = qh->qh_next.qh) {  		if (list_empty(&qh->qtd_list) &&  				qh->qh_state == QH_STATE_LINKED) { -			if (!stopped && qh->unlink_cycle == -					ehci->async_unlink_cycle) +			++count; +			if (qh->unlink_cycle == ehci->async_unlink_cycle)  				check_unlinks_later = true;  			else -				single_unlink_async(ehci, qh); +				qh_to_unlink = qh;  		}  	} -	/* Start a new IAA cycle if any QHs are waiting for it */ -	if (ehci->async_unlink) -		start_iaa_cycle(ehci, false); +	/* If nothing else is being unlinked, unlink the last empty QH */ +	if (!ehci->async_iaa && !ehci->async_unlink && qh_to_unlink) { +		start_unlink_async(ehci, qh_to_unlink); +		--count; +	} -	/* QHs that haven't been empty for long enough will be handled later */ -	if (check_unlinks_later) { +	/* Other QHs will be handled later */ +	if (count > 0) {  		ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true);  		++ehci->async_unlink_cycle;  	} diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 69ebee73c0c..b476daf49f6 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -213,7 +213,7 @@ static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask)  }  static const unsigned char -max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; +max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 125, 25 };  /* carryover low/fullspeed bandwidth that crosses uframe boundries */  static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) @@ -2212,11 +2212,11 @@ static void scan_isoc(struct ehci_hcd *ehci)  	}  	ehci->now_frame = now_frame; +	frame = ehci->last_iso_frame;  	for (;;) {  		union ehci_shadow	q, *q_p;  		__hc32			type, *hw_p; -		frame = ehci->last_iso_frame;  restart:  		/* scan each element in frame's queue for completions */  		q_p = &ehci->pshadow [frame]; @@ -2321,6 +2321,9 @@ restart:  		/* Stop when we have reached the current frame */  		if (frame == now_frame)  			break; -		ehci->last_iso_frame = (frame + 1) & fmask; + +		/* The last frame may still have active siTDs */ +		ehci->last_iso_frame = frame; +		frame = (frame + 1) & fmask;  	}  } diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c index 20dbdcbe9b0..f904071d70d 100644 --- a/drivers/usb/host/ehci-timer.c +++ b/drivers/usb/host/ehci-timer.c @@ -113,14 +113,15 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci)  	if (want != actual) { -		/* Poll again later, but give up after about 20 ms */ -		if (ehci->ASS_poll_count++ < 20) { -			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); -			return; -		} -		ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n", -				want, actual); +		/* Poll again later */ +		ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); +		++ehci->ASS_poll_count; +		return;  	} + +	if (ehci->ASS_poll_count > 20) +		ehci_dbg(ehci, "ASS poll count reached %d\n", +				ehci->ASS_poll_count);  	ehci->ASS_poll_count = 0;  	/* The status is up-to-date; restart or stop the schedule as needed */ @@ -159,14 +160,14 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)  	if (want != actual) { -		/* Poll again later, but give up after about 20 ms */ -		if (ehci->PSS_poll_count++ < 20) { -			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); -			return; -		} -		ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n", -				want, actual); +		/* Poll again later */ +		ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); +		return;  	} + +	if (ehci->PSS_poll_count > 20) +		ehci_dbg(ehci, "PSS poll count reached %d\n", +				ehci->PSS_poll_count);  	ehci->PSS_poll_count = 0;  	/* The status is up-to-date; restart or stop the schedule as needed */ diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index a3b6d7104ae..4c338ec03a0 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -780,6 +780,7 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)  				"defaulting to EHCI.\n");  		dev_warn(&xhci_pdev->dev,  				"USB 3.0 devices will work at USB 2.0 speeds.\n"); +		usb_disable_xhci_ports(xhci_pdev);  		return;  	} diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 768d54295a2..15d13229ddb 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c @@ -116,6 +116,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,  		}  	}  	clear_bit(port, &uhci->resuming_ports); +	usb_hcd_end_port_resume(&uhci_to_hcd(uhci)->self, port);  }  /* Wait for the UHCI controller in HP's iLO2 server management chip. @@ -167,6 +168,8 @@ static void uhci_check_ports(struct uhci_hcd *uhci)  				set_bit(port, &uhci->resuming_ports);  				uhci->ports_timeout = jiffies +  						msecs_to_jiffies(25); +				usb_hcd_start_port_resume( +						&uhci_to_hcd(uhci)->self, port);  				/* Make sure we see the port again  				 * after the resuming period is over. */ diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 59fb5c677db..7f76a49e90d 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1698,7 +1698,7 @@ static void handle_port_status(struct xhci_hcd *xhci,  				faked_port_index + 1);  		if (slot_id && xhci->devs[slot_id])  			xhci_ring_device(xhci, slot_id); -		if (bus_state->port_remote_wakeup && (1 << faked_port_index)) { +		if (bus_state->port_remote_wakeup & (1 << faked_port_index)) {  			bus_state->port_remote_wakeup &=  				~(1 << faked_port_index);  			xhci_test_and_clear_bit(xhci, port_array, @@ -2589,6 +2589,8 @@ cleanup:  				(trb_comp_code != COMP_STALL &&  					trb_comp_code != COMP_BABBLE))  				xhci_urb_free_priv(xhci, urb_priv); +			else +				kfree(urb_priv);  			usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);  			if ((urb->actual_length != urb->transfer_buffer_length && @@ -3108,7 +3110,7 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,  	 * running_total.  	 */  	packets_transferred = (running_total + trb_buff_len) / -		usb_endpoint_maxp(&urb->ep->desc); +		GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));  	if ((total_packet_count - packets_transferred) > 31)  		return 31 << 17; @@ -3642,7 +3644,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  		td_len = urb->iso_frame_desc[i].length;  		td_remain_len = td_len;  		total_packet_count = DIV_ROUND_UP(td_len, -				usb_endpoint_maxp(&urb->ep->desc)); +				GET_MAX_PACKET( +					usb_endpoint_maxp(&urb->ep->desc)));  		/* A zero-length transfer still involves at least one packet. */  		if (total_packet_count == 0)  			total_packet_count++; @@ -3664,9 +3667,11 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  		td = urb_priv->td[i];  		for (j = 0; j < trbs_per_td; j++) {  			u32 remainder = 0; -			field = TRB_TBC(burst_count) | TRB_TLBPC(residue); +			field = 0;  			if (first_trb) { +				field = TRB_TBC(burst_count) | +					TRB_TLBPC(residue);  				/* Queue the isoc TRB */  				field |= TRB_TYPE(TRB_ISOC);  				/* Assume URB_ISO_ASAP is set */  |