Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0d9efba authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman
Browse files

USB: centralize -EREMOTEIO handling



This patch (as969) continues the ongoing changes to the way HCDs
report URB statuses.  The programming interface has been simplified by
making usbcore responsible for clearing urb->hcpriv and for setting
-EREMOTEIO status when an URB with the URB_SHORT_NOT_OK flag ends up
as a short transfer.

By moving the work out of the HCDs, this removes a fair amount of
repeated code.

Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
CC: David Brownell <david-b@pacbell.net>
CC: Olav Kongas <ok@artecdesign.ee>
CC: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
CC: Tony Olech <tony.olech@elandigitalsystems.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent ee7d1f3f
Loading
Loading
Loading
Loading
+7 −2
Original line number Original line Diff line number Diff line
@@ -366,6 +366,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
	spin_unlock_irq(&hcd_root_hub_lock);
	spin_unlock_irq(&hcd_root_hub_lock);
	if (status)
	if (status)
		return status;
		return status;
	urb->hcpriv = hcd;	/* Indicate it's queued */


	cmd = (struct usb_ctrlrequest *) urb->setup_packet;
	cmd = (struct usb_ctrlrequest *) urb->setup_packet;
	typeReq  = (cmd->bRequestType << 8) | cmd->bRequest;
	typeReq  = (cmd->bRequestType << 8) | cmd->bRequest;
@@ -579,7 +580,6 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
			hcd->poll_pending = 0;
			hcd->poll_pending = 0;
			hcd->status_urb = NULL;
			hcd->status_urb = NULL;
			urb->status = 0;
			urb->status = 0;
			urb->hcpriv = NULL;
			urb->actual_length = length;
			urb->actual_length = length;
			memcpy(urb->transfer_buffer, buffer, length);
			memcpy(urb->transfer_buffer, buffer, length);


@@ -675,7 +675,6 @@ static int usb_rh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
			del_timer (&hcd->rh_timer);
			del_timer (&hcd->rh_timer);
		if (urb == hcd->status_urb) {
		if (urb == hcd->status_urb) {
			hcd->status_urb = NULL;
			hcd->status_urb = NULL;
			urb->hcpriv = NULL;
			usb_hcd_unlink_urb_from_ep(hcd, urb);
			usb_hcd_unlink_urb_from_ep(hcd, urb);


			spin_unlock(&hcd_root_hub_lock);
			spin_unlock(&hcd_root_hub_lock);
@@ -1192,6 +1191,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
	if (unlikely(status)) {
	if (unlikely(status)) {
		usbmon_urb_submit_error(&hcd->self, urb, status);
		usbmon_urb_submit_error(&hcd->self, urb, status);
		unmap_urb_for_dma(hcd, urb);
		unmap_urb_for_dma(hcd, urb);
		urb->hcpriv = NULL;
		INIT_LIST_HEAD(&urb->urb_list);
		INIT_LIST_HEAD(&urb->urb_list);
		atomic_dec(&urb->use_count);
		atomic_dec(&urb->use_count);
		if (urb->reject)
		if (urb->reject)
@@ -1265,6 +1265,11 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
	unmap_urb_for_dma(hcd, urb);
	unmap_urb_for_dma(hcd, urb);
	usbmon_urb_complete (&hcd->self, urb);
	usbmon_urb_complete (&hcd->self, urb);
	usb_unanchor_urb(urb);
	usb_unanchor_urb(urb);
	urb->hcpriv = NULL;
	if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
			urb->actual_length < urb->transfer_buffer_length &&
			!urb->status))
		urb->status = -EREMOTEIO;


	/* pass ownership to the completion handler */
	/* pass ownership to the completion handler */
	urb->complete (urb);
	urb->complete (urb);
+2 −7
Original line number Original line Diff line number Diff line
@@ -1099,8 +1099,7 @@ transfer (struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit)
		 *
		 *
		 * partially filling a buffer optionally blocks queue advances
		 * partially filling a buffer optionally blocks queue advances
		 * (so completion handlers can clean up the queue) but we don't
		 * (so completion handlers can clean up the queue) but we don't
		 * need to emulate such data-in-flight.  so we only show part
		 * need to emulate such data-in-flight.
		 * of the URB_SHORT_NOT_OK effect: completion status.
		 */
		 */
		if (is_short) {
		if (is_short) {
			if (host_len == dev_len) {
			if (host_len == dev_len) {
@@ -1111,10 +1110,7 @@ transfer (struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit)
				if (dev_len > host_len)
				if (dev_len > host_len)
					maybe_set_status (urb, -EOVERFLOW);
					maybe_set_status (urb, -EOVERFLOW);
				else
				else
					maybe_set_status (urb,
					maybe_set_status (urb, 0);
						(urb->transfer_flags
							& URB_SHORT_NOT_OK)
						? -EREMOTEIO : 0);
			} else if (!to_host) {
			} else if (!to_host) {
				maybe_set_status (urb, 0);
				maybe_set_status (urb, 0);
				if (host_len > dev_len)
				if (host_len > dev_len)
@@ -1516,7 +1512,6 @@ static void dummy_timer (unsigned long _dum)
			continue;
			continue;


return_urb:
return_urb:
		urb->hcpriv = NULL;
		list_del (&urbp->urbp_list);
		list_del (&urbp->urbp_list);
		kfree (urbp);
		kfree (urbp);
		if (ep)
		if (ep)
+4 −3
Original line number Original line Diff line number Diff line
@@ -232,7 +232,6 @@ __acquires(ehci->lock)
	}
	}


	spin_lock (&urb->lock);
	spin_lock (&urb->lock);
	urb->hcpriv = NULL;
	switch (urb->status) {
	switch (urb->status) {
	case -EINPROGRESS:		/* success */
	case -EINPROGRESS:		/* success */
		urb->status = 0;
		urb->status = 0;
@@ -395,8 +394,10 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
		/* remove it from the queue */
		/* remove it from the queue */
		spin_lock (&urb->lock);
		spin_lock (&urb->lock);
		qtd_copy_status (ehci, urb, qtd->length, token);
		qtd_copy_status (ehci, urb, qtd->length, token);
		do_status = (urb->status == -EREMOTEIO)
		if (unlikely(urb->status == -EREMOTEIO)) {
				&& usb_pipecontrol (urb->pipe);
			do_status = usb_pipecontrol(urb->pipe);
			urb->status = 0;
		}
		spin_unlock (&urb->lock);
		spin_unlock (&urb->lock);


		if (stopped && qtd->qtd_list.prev != &qh->qtd_list) {
		if (stopped && qtd->qtd_list.prev != &qh->qtd_list) {
+1 −7
Original line number Original line Diff line number Diff line
@@ -282,7 +282,6 @@ __releases(isp116x->lock) __acquires(isp116x->lock)
{
{
	unsigned i;
	unsigned i;


	urb->hcpriv = NULL;
	ep->error_count = 0;
	ep->error_count = 0;


	if (usb_pipecontrol(urb->pipe))
	if (usb_pipecontrol(urb->pipe))
@@ -446,11 +445,6 @@ static void postproc_atl_queue(struct isp116x *isp116x)
			if (PTD_GET_ACTIVE(ptd)
			if (PTD_GET_ACTIVE(ptd)
			    || (cc != TD_CC_NOERROR && cc < 0x0E))
			    || (cc != TD_CC_NOERROR && cc < 0x0E))
				break;
				break;
			if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
					urb->actual_length <
						urb->transfer_buffer_length)
				status = -EREMOTEIO;
			else
			status = 0;
			status = 0;
			ep->nextpid = 0;
			ep->nextpid = 0;
			break;
			break;
+0 −11
Original line number Original line Diff line number Diff line
@@ -43,21 +43,10 @@ __acquires(ohci->lock)
	// ASSERT (urb->hcpriv != 0);
	// ASSERT (urb->hcpriv != 0);


	urb_free_priv (ohci, urb->hcpriv);
	urb_free_priv (ohci, urb->hcpriv);
	urb->hcpriv = NULL;


	spin_lock (&urb->lock);
	spin_lock (&urb->lock);
	if (likely (urb->status == -EINPROGRESS))
	if (likely (urb->status == -EINPROGRESS))
		urb->status = 0;
		urb->status = 0;
	/* report short control reads right even though the data TD always
	 * has TD_R set.  (much simpler, but creates the 1-td limit.)
	 */
	if (unlikely (urb->transfer_flags & URB_SHORT_NOT_OK)
			&& unlikely (usb_pipecontrol (urb->pipe))
			&& urb->actual_length < urb->transfer_buffer_length
			&& usb_pipein (urb->pipe)
			&& urb->status == 0) {
		urb->status = -EREMOTEIO;
	}
	spin_unlock (&urb->lock);
	spin_unlock (&urb->lock);


	switch (usb_pipetype (urb->pipe)) {
	switch (usb_pipetype (urb->pipe)) {
Loading